annotate sites/all/modules/references/node_reference/node_reference.module @ 9:830c812b520f

added smtp module
author root <root@paio.local>
date Mon, 28 Oct 2013 15:34:27 +0000
parents ce11bbd8f642
children
rev   line source
danielebarchiesi@4 1 <?php
danielebarchiesi@4 2
danielebarchiesi@4 3 /**
danielebarchiesi@4 4 * @file
danielebarchiesi@4 5 * Defines a field type for referencing one node from another.
danielebarchiesi@4 6 */
danielebarchiesi@4 7
danielebarchiesi@4 8 /**
danielebarchiesi@4 9 * Implements hook_menu().
danielebarchiesi@4 10 */
danielebarchiesi@4 11 function node_reference_menu() {
danielebarchiesi@4 12 $items['node_reference/autocomplete/%/%/%'] = array(
danielebarchiesi@4 13 'page callback' => 'node_reference_autocomplete',
danielebarchiesi@4 14 'page arguments' => array(2, 3, 4),
danielebarchiesi@4 15 'access callback' => 'reference_autocomplete_access',
danielebarchiesi@4 16 'access arguments' => array(2, 3, 4),
danielebarchiesi@4 17 'type' => MENU_CALLBACK,
danielebarchiesi@4 18 );
danielebarchiesi@4 19 return $items;
danielebarchiesi@4 20 }
danielebarchiesi@4 21
danielebarchiesi@4 22 /**
danielebarchiesi@4 23 * Implements hook_field_info().
danielebarchiesi@4 24 */
danielebarchiesi@4 25 function node_reference_field_info() {
danielebarchiesi@4 26 return array(
danielebarchiesi@4 27 'node_reference' => array(
danielebarchiesi@4 28 'label' => t('Node reference'),
danielebarchiesi@4 29 'description' => t('This field stores the ID of a related node as an integer value.'),
danielebarchiesi@4 30 'settings' => array(
danielebarchiesi@4 31 'referenceable_types' => array(),
danielebarchiesi@4 32 'view' => array(
danielebarchiesi@4 33 'view_name' => '',
danielebarchiesi@4 34 'display_name' => '',
danielebarchiesi@4 35 'args' => array(),
danielebarchiesi@4 36 ),
danielebarchiesi@4 37 ),
danielebarchiesi@4 38 // It probably make more sense to have the referenceable types be per-field than per-instance
danielebarchiesi@4 39 // 'instance settings' => array('referenceable_types' => array()),
danielebarchiesi@4 40 'default_widget' => 'options_select', // node_reference_autocomplete',
danielebarchiesi@4 41 'default_formatter' => 'node_reference_default',
danielebarchiesi@4 42 // Support hook_entity_property_info() from contrib "Entity API".
danielebarchiesi@4 43 'property_type' => 'node',
danielebarchiesi@4 44 // Support default token formatter for field tokens.
danielebarchiesi@4 45 'default_token_formatter' => 'node_reference_plain',
danielebarchiesi@4 46 ),
danielebarchiesi@4 47 );
danielebarchiesi@4 48 }
danielebarchiesi@4 49
danielebarchiesi@4 50 /**
danielebarchiesi@4 51 * Implements hook_field_settings_form().
danielebarchiesi@4 52 */
danielebarchiesi@4 53 function node_reference_field_settings_form($field, $instance, $has_data) {
danielebarchiesi@4 54 $settings = $field['settings'];
danielebarchiesi@4 55
danielebarchiesi@4 56 $form = array();
danielebarchiesi@4 57 $form['referenceable_types'] = array(
danielebarchiesi@4 58 '#type' => 'checkboxes',
danielebarchiesi@4 59 '#title' => t('Content types that can be referenced'),
danielebarchiesi@4 60 '#multiple' => TRUE,
danielebarchiesi@4 61 '#default_value' => $settings['referenceable_types'],
danielebarchiesi@4 62 '#options' => array_map('check_plain', node_type_get_names()),
danielebarchiesi@4 63 );
danielebarchiesi@4 64
danielebarchiesi@4 65 if (module_exists('views')) {
danielebarchiesi@4 66 $view_settings = $settings['view'];
danielebarchiesi@4 67
danielebarchiesi@4 68 $description = '<p>' . t('The list of nodes that can be referenced can provided by a view (Views module) using the "References" display type.') . '</p>';
danielebarchiesi@4 69
danielebarchiesi@4 70 // Special note for legacy fields migrated from D6.
danielebarchiesi@4 71 if (!empty($view_settings['view_name']) && $view_settings['display_name'] == 'default') {
danielebarchiesi@4 72 $description .= '<p><strong><span class="admin-missing">'. t("Important D6 migration note:") . '</span></strong>';
danielebarchiesi@4 73 $description .= '<br/>' . t("The field is currently configured to use the 'Master' display of the view %view_name.", array('%view_name' => $view_settings['view_name']));
danielebarchiesi@4 74 $description .= '<br/>' . t("It is highly recommended that you: <br/>- edit this view and create a new display using the 'References' display type, <br/>- update the field settings to explicitly select the correct view and display.");
danielebarchiesi@4 75 $description .= '<br/>' . t("The field will work correctly until then, but submitting this form might inadvertently change the field settings.") . '</p>';
danielebarchiesi@4 76 }
danielebarchiesi@4 77
danielebarchiesi@4 78 $form['view'] = array(
danielebarchiesi@4 79 '#type' => 'fieldset',
danielebarchiesi@4 80 '#title' => t('Views - Nodes that can be referenced'),
danielebarchiesi@4 81 '#collapsible' => TRUE,
danielebarchiesi@4 82 '#collapsed' => empty($view_settings['view_name']),
danielebarchiesi@4 83 '#description' => $description,
danielebarchiesi@4 84 );
danielebarchiesi@4 85
danielebarchiesi@4 86 $views_options = references_get_views_options('node');
danielebarchiesi@4 87 if ($views_options) {
danielebarchiesi@4 88 // The value of the 'view_and_display' select below will need to be split
danielebarchiesi@4 89 // into 'view_name' and 'view_display' in the final submitted values, so
danielebarchiesi@4 90 // we massage the data at validate time on the wrapping element (not
danielebarchiesi@4 91 // ideal).
danielebarchiesi@4 92 $form['view']['#element_validate'] = array('_node_reference_view_settings_validate');
danielebarchiesi@4 93
danielebarchiesi@4 94 $views_options = array('' => '<' . t('none') . '>') + $views_options;
danielebarchiesi@4 95 $default = empty($view_settings['view_name']) ? '' : $view_settings['view_name'] . ':' .$view_settings['display_name'];
danielebarchiesi@4 96 $form['view']['view_and_display'] = array(
danielebarchiesi@4 97 '#type' => 'select',
danielebarchiesi@4 98 '#title' => t('View used to select the nodes'),
danielebarchiesi@4 99 '#options' => $views_options,
danielebarchiesi@4 100 '#default_value' => $default,
danielebarchiesi@4 101 '#description' => '<p>' . t('Choose the view and display that select the nodes that can be referenced.<br />Only views with a display of type "References" are eligible.') . '</p>' .
danielebarchiesi@4 102 t('Note:<ul><li>This will discard the "Content types" settings above. Use the view\'s "filters" section instead.</li><li>Use the view\'s "fields" section to display additional informations about candidate nodes on node creation/edition form.</li><li>Use the view\'s "sort criteria" section to determine the order in which candidate nodes will be displayed.</li></ul>'),
danielebarchiesi@4 103 );
danielebarchiesi@4 104
danielebarchiesi@4 105 $default = implode(', ', $view_settings['args']);
danielebarchiesi@4 106 $form['view']['args'] = array(
danielebarchiesi@4 107 '#type' => 'textfield',
danielebarchiesi@4 108 '#title' => t('View arguments'),
danielebarchiesi@4 109 '#default_value' => $default,
danielebarchiesi@4 110 '#required' => FALSE,
danielebarchiesi@4 111 '#description' => t('Provide a comma separated list of arguments to pass to the view.'),
danielebarchiesi@4 112 );
danielebarchiesi@4 113 }
danielebarchiesi@4 114 else {
danielebarchiesi@4 115 $form['view']['no_view_help'] = array(
danielebarchiesi@4 116 '#markup' => '<p>' . t('No eligible view was found.') .'</p>',
danielebarchiesi@4 117 );
danielebarchiesi@4 118 }
danielebarchiesi@4 119 }
danielebarchiesi@4 120
danielebarchiesi@4 121 return $form;
danielebarchiesi@4 122 }
danielebarchiesi@4 123
danielebarchiesi@4 124 /**
danielebarchiesi@4 125 * Validate callback for the 'view settings' fieldset.
danielebarchiesi@4 126 *
danielebarchiesi@4 127 * Puts back the various form values in the expected shape.
danielebarchiesi@4 128 */
danielebarchiesi@4 129 function _node_reference_view_settings_validate($element, &$form_state, $form) {
danielebarchiesi@4 130 // Split view name and display name from the 'view_and_display' value.
danielebarchiesi@4 131 if (!empty($element['view_and_display']['#value'])) {
danielebarchiesi@4 132 list($view, $display) = explode(':', $element['view_and_display']['#value']);
danielebarchiesi@4 133 }
danielebarchiesi@4 134 else {
danielebarchiesi@4 135 $view = '';
danielebarchiesi@4 136 $display = '';
danielebarchiesi@4 137 }
danielebarchiesi@4 138
danielebarchiesi@4 139 // Explode the 'args' string into an actual array. Beware, explode() turns an
danielebarchiesi@4 140 // empty string into an array with one empty string. We'll need an empty array
danielebarchiesi@4 141 // instead.
danielebarchiesi@4 142 $args_string = trim($element['args']['#value']);
danielebarchiesi@4 143 $args = ($args_string === '') ? array() : array_map('trim', explode(',', $args_string));
danielebarchiesi@4 144
danielebarchiesi@4 145 $value = array('view_name' => $view, 'display_name' => $display, 'args' => $args);
danielebarchiesi@4 146 form_set_value($element, $value, $form_state);
danielebarchiesi@4 147 }
danielebarchiesi@4 148
danielebarchiesi@4 149 /**
danielebarchiesi@4 150 * Implements hook_field_validate().
danielebarchiesi@4 151 *
danielebarchiesi@4 152 * Possible error codes:
danielebarchiesi@4 153 * - 'invalid_nid': nid is not valid for the field (not a valid node id, or the node is not referenceable).
danielebarchiesi@4 154 */
danielebarchiesi@4 155 function node_reference_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) {
danielebarchiesi@4 156 // Extract nids to check.
danielebarchiesi@4 157 $ids = array();
danielebarchiesi@4 158
danielebarchiesi@4 159 // First check non-numeric "nid's to avoid losing time with them.
danielebarchiesi@4 160 foreach ($items as $delta => $item) {
danielebarchiesi@4 161 if (is_array($item) && !empty($item['nid'])) {
danielebarchiesi@4 162 if (is_numeric($item['nid'])) {
danielebarchiesi@4 163 $ids[] = $item['nid'];
danielebarchiesi@4 164 }
danielebarchiesi@4 165 else {
danielebarchiesi@4 166 $errors[$field['field_name']][$langcode][$delta][] = array(
danielebarchiesi@4 167 'error' => 'invalid_nid',
danielebarchiesi@4 168 'message' => t("%name: invalid input.",
danielebarchiesi@4 169 array('%name' => $instance['label'])),
danielebarchiesi@4 170 );
danielebarchiesi@4 171 }
danielebarchiesi@4 172 }
danielebarchiesi@4 173 }
danielebarchiesi@4 174 // Prevent performance hog if there are no ids to check.
danielebarchiesi@4 175 if ($ids) {
danielebarchiesi@4 176 $options = array(
danielebarchiesi@4 177 'ids' => $ids,
danielebarchiesi@4 178 );
danielebarchiesi@4 179 $refs = node_reference_potential_references($field, $options);
danielebarchiesi@4 180 foreach ($items as $delta => $item) {
danielebarchiesi@4 181 if (is_array($item)) {
danielebarchiesi@4 182 if (!empty($item['nid']) && !isset($refs[$item['nid']])) {
danielebarchiesi@4 183 $errors[$field['field_name']][$langcode][$delta][] = array(
danielebarchiesi@4 184 'error' => 'invalid_nid',
danielebarchiesi@4 185 'message' => t("%name: this post can't be referenced.",
danielebarchiesi@4 186 array('%name' => $instance['label'])),
danielebarchiesi@4 187 );
danielebarchiesi@4 188 }
danielebarchiesi@4 189 }
danielebarchiesi@4 190 }
danielebarchiesi@4 191 }
danielebarchiesi@4 192 }
danielebarchiesi@4 193
danielebarchiesi@4 194 /**
danielebarchiesi@4 195 * Implements hook_field_prepare_view().
danielebarchiesi@4 196 */
danielebarchiesi@4 197 function node_reference_field_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items) {
danielebarchiesi@4 198 $checked_ids = &drupal_static(__FUNCTION__, array());
danielebarchiesi@4 199
danielebarchiesi@4 200 // Set an 'access' property on each item (TRUE if the node exists and is
danielebarchiesi@4 201 // accessible by the current user).
danielebarchiesi@4 202
danielebarchiesi@4 203 // Extract ids to check.
danielebarchiesi@4 204 $ids = array();
danielebarchiesi@4 205 foreach ($items as $id => $entity_items) {
danielebarchiesi@4 206 foreach ($entity_items as $delta => $item) {
danielebarchiesi@4 207 if (is_array($item)) {
danielebarchiesi@4 208 // Default to 'not accessible'.
danielebarchiesi@4 209 $items[$id][$delta]['access'] = FALSE;
danielebarchiesi@4 210 if (!empty($item['nid']) && is_numeric($item['nid'])) {
danielebarchiesi@4 211 $ids[$item['nid']] = $item['nid'];
danielebarchiesi@4 212 }
danielebarchiesi@4 213 }
danielebarchiesi@4 214 }
danielebarchiesi@4 215 }
danielebarchiesi@4 216
danielebarchiesi@4 217 if ($ids) {
danielebarchiesi@4 218 // Load information about ids that we haven't already loaded during this
danielebarchiesi@4 219 // page request.
danielebarchiesi@4 220 $ids_to_check = array_diff($ids, array_keys($checked_ids));
danielebarchiesi@4 221 if (!empty($ids_to_check)) {
danielebarchiesi@4 222 $query = db_select('node', 'n')
danielebarchiesi@4 223 ->addTag('node_access')
danielebarchiesi@4 224 ->addMetaData('id', 'node_reference_field_prepare_view')
danielebarchiesi@4 225 ->addMetaData('field', $field)
danielebarchiesi@4 226 ->fields('n', array('nid'))
danielebarchiesi@4 227 // WHERE n.nid IN (nids to check) AND ...
danielebarchiesi@4 228 ->condition('n.nid', $ids_to_check, 'IN');
danielebarchiesi@4 229
danielebarchiesi@4 230 // Unless the user has the right permissions, restrict on the node status.
danielebarchiesi@4 231 // (note: the 'view any unpublished content' permission is provided by the
danielebarchiesi@4 232 // 'view_unpublished' contrib module.)
danielebarchiesi@4 233 if (!user_access('bypass node access') && !user_access('view any unpublished content')) {
danielebarchiesi@4 234 // ... AND n.status = 1
danielebarchiesi@4 235 $status_condition = db_or()
danielebarchiesi@4 236 ->condition('n.status', NODE_PUBLISHED);
danielebarchiesi@4 237
danielebarchiesi@4 238 // Take the 'view own unpublished content' permission into account to
danielebarchiesi@4 239 // decide whether some unpublished nodes should still be visible.
danielebarchiesi@4 240 if (user_access('view own unpublished content') && $own_unpublished = db_query('SELECT nid FROM {node} WHERE uid = :uid AND status = :status', array(':uid' => $GLOBALS['user']->uid, ':status' => NODE_NOT_PUBLISHED))->fetchCol()) {
danielebarchiesi@4 241 // ... AND (n.status = 1 OR n.nid IN (own unpublished))
danielebarchiesi@4 242 $status_condition
danielebarchiesi@4 243 ->condition('n.nid', $own_unpublished, 'IN');
danielebarchiesi@4 244 }
danielebarchiesi@4 245
danielebarchiesi@4 246 $query->condition($status_condition);
danielebarchiesi@4 247 }
danielebarchiesi@4 248
danielebarchiesi@4 249 $accessible_ids = $query->execute()->fetchAllAssoc('nid');
danielebarchiesi@4 250
danielebarchiesi@4 251 // Populate our static list so that we do not query on those ids again.
danielebarchiesi@4 252 foreach ($ids_to_check as $id) {
danielebarchiesi@4 253 $checked_ids[$id] = isset($accessible_ids[$id]);
danielebarchiesi@4 254 }
danielebarchiesi@4 255 }
danielebarchiesi@4 256
danielebarchiesi@4 257 foreach ($items as $id => $entity_items) {
danielebarchiesi@4 258 foreach ($entity_items as $delta => $item) {
danielebarchiesi@4 259 if (is_array($item) && !empty($item['nid']) && !empty($checked_ids[$item['nid']])) {
danielebarchiesi@4 260 $items[$id][$delta]['access'] = TRUE;
danielebarchiesi@4 261 }
danielebarchiesi@4 262 }
danielebarchiesi@4 263 }
danielebarchiesi@4 264 }
danielebarchiesi@4 265 }
danielebarchiesi@4 266
danielebarchiesi@4 267 /**
danielebarchiesi@4 268 * Implements hook_field_is_empty().
danielebarchiesi@4 269 */
danielebarchiesi@4 270 function node_reference_field_is_empty($item, $field) {
danielebarchiesi@4 271 // nid = 0 is empty too, which is exactly what we want.
danielebarchiesi@4 272 return empty($item['nid']);
danielebarchiesi@4 273 }
danielebarchiesi@4 274
danielebarchiesi@4 275 /**
danielebarchiesi@4 276 * Implements hook_field_formatter_info().
danielebarchiesi@4 277 */
danielebarchiesi@4 278 function node_reference_field_formatter_info() {
danielebarchiesi@4 279 $ret = array(
danielebarchiesi@4 280 'node_reference_default' => array(
danielebarchiesi@4 281 'label' => t('Title (link)'),
danielebarchiesi@4 282 'description' => t('Display the title of the referenced node as a link to the node page.'),
danielebarchiesi@4 283 'field types' => array('node_reference'),
danielebarchiesi@4 284 ),
danielebarchiesi@4 285 'node_reference_plain' => array(
danielebarchiesi@4 286 'label' => t('Title (no link)'),
danielebarchiesi@4 287 'description' => t('Display the title of the referenced node as plain text.'),
danielebarchiesi@4 288 'field types' => array('node_reference'),
danielebarchiesi@4 289 ),
danielebarchiesi@4 290 'node_reference_node' => array(
danielebarchiesi@4 291 'label' => t('Rendered node'),
danielebarchiesi@4 292 'description' => t('Display the referenced node in a specific view mode'),
danielebarchiesi@4 293 'field types' => array('node_reference'),
danielebarchiesi@4 294 'settings' => array('node_reference_view_mode' => 'full'),
danielebarchiesi@4 295 ),
danielebarchiesi@4 296 'node_reference_nid' => array(
danielebarchiesi@4 297 'label' => t('Node ID'),
danielebarchiesi@4 298 'description' => t('Display the referenced node ID'),
danielebarchiesi@4 299 'field types' => array('node_reference'),
danielebarchiesi@4 300 ),
danielebarchiesi@4 301 'node_reference_path' => array(
danielebarchiesi@4 302 'label' => t('URL as plain text'),
danielebarchiesi@4 303 'description' => t('Display the URL of the referenced node'),
danielebarchiesi@4 304 'field types' => array('node_reference'),
danielebarchiesi@4 305 'settings' => array(
danielebarchiesi@4 306 'alias' => TRUE,
danielebarchiesi@4 307 'absolute' => FALSE
danielebarchiesi@4 308 ),
danielebarchiesi@4 309 ),
danielebarchiesi@4 310 );
danielebarchiesi@4 311 return $ret;
danielebarchiesi@4 312 }
danielebarchiesi@4 313
danielebarchiesi@4 314 /**
danielebarchiesi@4 315 * Implements hook_field_formatter_settings_form().
danielebarchiesi@4 316 */
danielebarchiesi@4 317 function node_reference_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
danielebarchiesi@4 318 $display = $instance['display'][$view_mode];
danielebarchiesi@4 319 $settings = $display['settings'];
danielebarchiesi@4 320
danielebarchiesi@4 321 $element = array();
danielebarchiesi@4 322
danielebarchiesi@4 323 switch ($display['type']) {
danielebarchiesi@4 324 case 'node_reference_node':
danielebarchiesi@4 325 $entity_info = entity_get_info('node');
danielebarchiesi@4 326 $modes = $entity_info['view modes'];
danielebarchiesi@4 327 $options = array();
danielebarchiesi@4 328 foreach ($modes as $name => $mode) {
danielebarchiesi@4 329 $options[$name] = $mode['label'];
danielebarchiesi@4 330 }
danielebarchiesi@4 331 $element['node_reference_view_mode'] = array(
danielebarchiesi@4 332 '#title' => t('View mode'),
danielebarchiesi@4 333 '#type' => 'select',
danielebarchiesi@4 334 '#options' => $options,
danielebarchiesi@4 335 '#default_value' => $settings['node_reference_view_mode'],
danielebarchiesi@4 336 // Never empty, so no #empty_option
danielebarchiesi@4 337 );
danielebarchiesi@4 338 break;
danielebarchiesi@4 339
danielebarchiesi@4 340 case 'node_reference_path':
danielebarchiesi@4 341 $element['alias'] = array(
danielebarchiesi@4 342 '#type' => 'checkbox',
danielebarchiesi@4 343 '#title' => t('Display the aliased path (if exists) instead of the system path'),
danielebarchiesi@4 344 '#default_value' => $settings['alias'],
danielebarchiesi@4 345 );
danielebarchiesi@4 346 $element['absolute'] = array(
danielebarchiesi@4 347 '#type' => 'checkbox',
danielebarchiesi@4 348 '#title' => t('Display an absolute URL'),
danielebarchiesi@4 349 '#default_value' => $settings['absolute'],
danielebarchiesi@4 350 );
danielebarchiesi@4 351 break;
danielebarchiesi@4 352 }
danielebarchiesi@4 353
danielebarchiesi@4 354 return $element;
danielebarchiesi@4 355 }
danielebarchiesi@4 356
danielebarchiesi@4 357 /**
danielebarchiesi@4 358 * Implements hook_field_formatter_settings_summary().
danielebarchiesi@4 359 */
danielebarchiesi@4 360 function node_reference_field_formatter_settings_summary($field, $instance, $view_mode) {
danielebarchiesi@4 361 $display = $instance['display'][$view_mode];
danielebarchiesi@4 362 $settings = $display['settings'];
danielebarchiesi@4 363 $summary = array();
danielebarchiesi@4 364
danielebarchiesi@4 365 switch ($display['type']) {
danielebarchiesi@4 366 case 'node_reference_node':
danielebarchiesi@4 367 $entity_info = entity_get_info('node');
danielebarchiesi@4 368 $modes = $entity_info['view modes'];
danielebarchiesi@4 369 $mode = $modes[$settings['node_reference_view_mode']]['label'];
danielebarchiesi@4 370 $summary[] = t('View mode: %mode', array('%mode' => $mode));
danielebarchiesi@4 371 break;
danielebarchiesi@4 372
danielebarchiesi@4 373 case 'node_reference_path':
danielebarchiesi@4 374 $summary[] = t('Aliased path: %yes_no', array('%yes_no' => $settings['alias'] ? t('Yes') : t('No')));
danielebarchiesi@4 375 $summary[] = t('Absolute URL: %yes_no', array('%yes_no' => $settings['absolute'] ? t('Yes') : t('No')));
danielebarchiesi@4 376 break;
danielebarchiesi@4 377 }
danielebarchiesi@4 378
danielebarchiesi@4 379 return implode('<br />', $summary);
danielebarchiesi@4 380 }
danielebarchiesi@4 381
danielebarchiesi@4 382 /**
danielebarchiesi@4 383 * Implements hook_field_formatter_prepare_view().
danielebarchiesi@4 384 *
danielebarchiesi@4 385 * Preload all nodes referenced by items using 'full entity' formatters.
danielebarchiesi@4 386 */
danielebarchiesi@4 387 function node_reference_field_formatter_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items, $displays) {
danielebarchiesi@4 388 // Load the referenced nodes, except for the 'node_reference_nid' which does
danielebarchiesi@4 389 // not need full objects.
danielebarchiesi@4 390
danielebarchiesi@4 391 // Collect ids to load.
danielebarchiesi@4 392 $ids = array();
danielebarchiesi@4 393 foreach ($displays as $id => $display) {
danielebarchiesi@4 394 if ($display['type'] != 'node_reference_nid') {
danielebarchiesi@4 395 foreach ($items[$id] as $delta => $item) {
danielebarchiesi@4 396 if ($item['access']) {
danielebarchiesi@4 397 $ids[$item['nid']] = $item['nid'];
danielebarchiesi@4 398 }
danielebarchiesi@4 399 }
danielebarchiesi@4 400 }
danielebarchiesi@4 401 }
danielebarchiesi@4 402 $entities = node_load_multiple($ids);
danielebarchiesi@4 403
danielebarchiesi@4 404 // Add the loaded nodes to the items.
danielebarchiesi@4 405 foreach ($displays as $id => $display) {
danielebarchiesi@4 406 if ($display['type'] != 'node_reference_nid') {
danielebarchiesi@4 407 foreach ($items[$id] as $delta => $item) {
danielebarchiesi@4 408 if ($item['access']) {
danielebarchiesi@4 409 $items[$id][$delta]['node'] = $entities[$item['nid']];
danielebarchiesi@4 410 }
danielebarchiesi@4 411 }
danielebarchiesi@4 412 }
danielebarchiesi@4 413 }
danielebarchiesi@4 414 }
danielebarchiesi@4 415
danielebarchiesi@4 416 /**
danielebarchiesi@4 417 * Implements hook_field_formatter_view().
danielebarchiesi@4 418 */
danielebarchiesi@4 419 function node_reference_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
danielebarchiesi@4 420 $settings = $display['settings'];
danielebarchiesi@4 421 $result = array();
danielebarchiesi@4 422
danielebarchiesi@4 423 switch ($display['type']) {
danielebarchiesi@4 424 case 'node_reference_default':
danielebarchiesi@4 425 case 'node_reference_plain':
danielebarchiesi@4 426 foreach ($items as $delta => $item) {
danielebarchiesi@4 427 if ($item['access']) {
danielebarchiesi@4 428 $node = $item['node'];
danielebarchiesi@4 429 $label = entity_label('node', $node);
danielebarchiesi@4 430 if ($display['type'] == 'node_reference_default') {
danielebarchiesi@4 431 $uri = entity_uri('node', $node);
danielebarchiesi@4 432 $result[$delta] = array(
danielebarchiesi@4 433 '#type' => 'link',
danielebarchiesi@4 434 '#title' => $label,
danielebarchiesi@4 435 '#href' => $uri['path'],
danielebarchiesi@4 436 '#options' => $uri['options'],
danielebarchiesi@4 437 );
danielebarchiesi@4 438 }
danielebarchiesi@4 439 else {
danielebarchiesi@4 440 $result[$delta] = array(
danielebarchiesi@4 441 '#markup' => check_plain($label),
danielebarchiesi@4 442 );
danielebarchiesi@4 443 }
danielebarchiesi@4 444 if (!$node->status) {
danielebarchiesi@4 445 $result[$delta]['#prefix'] = '<span class="node-unpublished">';
danielebarchiesi@4 446 $result[$delta]['#suffix'] = '</span>';
danielebarchiesi@4 447 }
danielebarchiesi@4 448 }
danielebarchiesi@4 449 }
danielebarchiesi@4 450 break;
danielebarchiesi@4 451
danielebarchiesi@4 452 case 'node_reference_node':
danielebarchiesi@4 453 // To prevent infinite recursion caused by reference cycles, we store
danielebarchiesi@4 454 // diplayed nodes in a recursion queue.
danielebarchiesi@4 455 $recursion_queue = &drupal_static(__FUNCTION__, array());
danielebarchiesi@4 456
danielebarchiesi@4 457 // If no 'referencing entity' is set, we are starting a new 'reference
danielebarchiesi@4 458 // thread' and need to reset the queue.
danielebarchiesi@4 459 // @todo Bug: $entity->referencing_entity on nodes referenced in a different
danielebarchiesi@4 460 // thread on the page. E.g: 1 references 1+2 / 2 references 1+2 / visit homepage.
danielebarchiesi@4 461 // We'd need a more accurate way...
danielebarchiesi@4 462 if (!isset($entity->referencing_entity)) {
danielebarchiesi@4 463 $recursion_queue = array();
danielebarchiesi@4 464 }
danielebarchiesi@4 465
danielebarchiesi@4 466 // The recursion queue only needs to track nodes.
danielebarchiesi@4 467 if ($entity_type == 'node') {
danielebarchiesi@4 468 list($id) = entity_extract_ids($entity_type, $entity);
danielebarchiesi@4 469 $recursion_queue[$id] = $id;
danielebarchiesi@4 470 }
danielebarchiesi@4 471
danielebarchiesi@4 472 // Check the recursion queue to determine which nodes should be fully
danielebarchiesi@4 473 // displayed, and which nodes will only be displayed as a title.
danielebarchiesi@4 474 $nodes_display = array();
danielebarchiesi@4 475 foreach ($items as $delta => $item) {
danielebarchiesi@4 476 if ($item['access'] && !isset($recursion_queue[$item['nid']])) {
danielebarchiesi@4 477 $nodes_display[$item['nid']] = $item['node'];
danielebarchiesi@4 478 }
danielebarchiesi@4 479 }
danielebarchiesi@4 480
danielebarchiesi@4 481 // Load and build the fully displayed nodes.
danielebarchiesi@4 482 if ($nodes_display) {
danielebarchiesi@4 483 foreach ($nodes_display as $nid => $node) {
danielebarchiesi@4 484 $nodes_display[$nid]->referencing_entity = $entity;
danielebarchiesi@4 485 $nodes_display[$nid]->referencing_field = $field['field_name'];
danielebarchiesi@4 486 }
danielebarchiesi@4 487 $nodes_built = node_view_multiple($nodes_display, $settings['node_reference_view_mode']);
danielebarchiesi@4 488 }
danielebarchiesi@4 489
danielebarchiesi@4 490 // Assemble the render array.
danielebarchiesi@4 491 foreach ($items as $delta => $item) {
danielebarchiesi@4 492 if ($item['access']) {
danielebarchiesi@4 493 if (isset($nodes_display[$item['nid']])) {
danielebarchiesi@4 494 $result[$delta] = $nodes_built['nodes'][$item['nid']];
danielebarchiesi@4 495 }
danielebarchiesi@4 496 else {
danielebarchiesi@4 497 $node = $item['node'];
danielebarchiesi@4 498 $label = entity_label('node', $node);
danielebarchiesi@4 499 $uri = entity_uri('node', $node);
danielebarchiesi@4 500 $result[$delta] = array(
danielebarchiesi@4 501 '#type' => 'link',
danielebarchiesi@4 502 '#title' => $label,
danielebarchiesi@4 503 '#href' => $uri['path'],
danielebarchiesi@4 504 '#options' => $uri['options'],
danielebarchiesi@4 505 );
danielebarchiesi@4 506 if (!$node->status) {
danielebarchiesi@4 507 $result[$delta]['#prefix'] = '<span class="node-unpublished">';
danielebarchiesi@4 508 $result[$delta]['#suffix'] = '</span>';
danielebarchiesi@4 509 }
danielebarchiesi@4 510 }
danielebarchiesi@4 511 }
danielebarchiesi@4 512 }
danielebarchiesi@4 513 break;
danielebarchiesi@4 514
danielebarchiesi@4 515 case 'node_reference_nid':
danielebarchiesi@4 516 foreach ($items as $delta => $item) {
danielebarchiesi@4 517 if ($item['access']) {
danielebarchiesi@4 518 $result[$delta] = array(
danielebarchiesi@4 519 '#markup' => $item['nid'],
danielebarchiesi@4 520 );
danielebarchiesi@4 521 }
danielebarchiesi@4 522 }
danielebarchiesi@4 523 break;
danielebarchiesi@4 524
danielebarchiesi@4 525 case 'node_reference_path':
danielebarchiesi@4 526 foreach ($items as $delta => $item) {
danielebarchiesi@4 527 if ($item['access']) {
danielebarchiesi@4 528 $uri = entity_uri('node', $item['node']);
danielebarchiesi@4 529 $options = array(
danielebarchiesi@4 530 'absolute' => $settings['absolute'],
danielebarchiesi@4 531 'alias' => !$settings['alias'],
danielebarchiesi@4 532 );
danielebarchiesi@4 533
danielebarchiesi@4 534 $options += $uri['options'];
danielebarchiesi@4 535 $result[$delta] = array(
danielebarchiesi@4 536 '#markup' => url($uri['path'], $options),
danielebarchiesi@4 537 );
danielebarchiesi@4 538 }
danielebarchiesi@4 539 }
danielebarchiesi@4 540 break;
danielebarchiesi@4 541 }
danielebarchiesi@4 542
danielebarchiesi@4 543 return $result;
danielebarchiesi@4 544 }
danielebarchiesi@4 545
danielebarchiesi@4 546 /**
danielebarchiesi@4 547 * Implements hook_field_widget_info().
danielebarchiesi@4 548 */
danielebarchiesi@4 549 function node_reference_field_widget_info() {
danielebarchiesi@4 550 return array(
danielebarchiesi@4 551 'node_reference_autocomplete' => array(
danielebarchiesi@4 552 'label' => t('Autocomplete text field'),
danielebarchiesi@4 553 'description' => t('Display the list of referenceable nodes as a textfield with autocomplete behaviour.'),
danielebarchiesi@4 554 'field types' => array('node_reference'),
danielebarchiesi@4 555 'settings' => array(
danielebarchiesi@4 556 'autocomplete_match' => 'contains',
danielebarchiesi@4 557 'size' => 60,
danielebarchiesi@4 558 'autocomplete_path' => 'node_reference/autocomplete',
danielebarchiesi@4 559 ),
danielebarchiesi@4 560 ),
danielebarchiesi@4 561 );
danielebarchiesi@4 562 }
danielebarchiesi@4 563
danielebarchiesi@4 564 /**
danielebarchiesi@4 565 * Implements hook_field_widget_info_alter().
danielebarchiesi@4 566 */
danielebarchiesi@4 567 function node_reference_field_widget_info_alter(&$info) {
danielebarchiesi@4 568 $info['options_select']['field types'][] = 'node_reference';
danielebarchiesi@4 569 $info['options_buttons']['field types'][] = 'node_reference';
danielebarchiesi@4 570 }
danielebarchiesi@4 571
danielebarchiesi@4 572 /**
danielebarchiesi@4 573 * Implements hook_field_widget_settings_form().
danielebarchiesi@4 574 */
danielebarchiesi@4 575 function node_reference_field_widget_settings_form($field, $instance) {
danielebarchiesi@4 576 $widget = $instance['widget'];
danielebarchiesi@4 577 $defaults = field_info_widget_settings($widget['type']);
danielebarchiesi@4 578 $settings = array_merge($defaults, $widget['settings']);
danielebarchiesi@4 579
danielebarchiesi@4 580 $form = array();
danielebarchiesi@4 581 if ($widget['type'] == 'node_reference_autocomplete') {
danielebarchiesi@4 582 $form['autocomplete_match'] = array(
danielebarchiesi@4 583 '#type' => 'select',
danielebarchiesi@4 584 '#title' => t('Autocomplete matching'),
danielebarchiesi@4 585 '#default_value' => $settings['autocomplete_match'],
danielebarchiesi@4 586 '#options' => array(
danielebarchiesi@4 587 'starts_with' => t('Starts with'),
danielebarchiesi@4 588 'contains' => t('Contains'),
danielebarchiesi@4 589 ),
danielebarchiesi@4 590 '#description' => t('Select the method used to collect autocomplete suggestions. Note that <em>Contains</em> can cause performance issues on sites with thousands of nodes.'),
danielebarchiesi@4 591 );
danielebarchiesi@4 592 $form['size'] = array(
danielebarchiesi@4 593 '#type' => 'textfield',
danielebarchiesi@4 594 '#title' => t('Size of textfield'),
danielebarchiesi@4 595 '#default_value' => $settings['size'],
danielebarchiesi@4 596 '#element_validate' => array('_element_validate_integer_positive'),
danielebarchiesi@4 597 '#required' => TRUE,
danielebarchiesi@4 598 );
danielebarchiesi@4 599 }
danielebarchiesi@4 600 return $form;
danielebarchiesi@4 601 }
danielebarchiesi@4 602
danielebarchiesi@4 603 /**
danielebarchiesi@4 604 * Implements hook_field_widget_form().
danielebarchiesi@4 605 */
danielebarchiesi@4 606 function node_reference_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
danielebarchiesi@4 607 switch ($instance['widget']['type']) {
danielebarchiesi@4 608 case 'node_reference_autocomplete':
danielebarchiesi@4 609 $element += array(
danielebarchiesi@4 610 '#type' => 'textfield',
danielebarchiesi@4 611 '#default_value' => isset($items[$delta]['nid']) ? $items[$delta]['nid'] : NULL,
danielebarchiesi@4 612 '#autocomplete_path' => $instance['widget']['settings']['autocomplete_path'] . '/' . $instance['entity_type'] . '/' . $instance['bundle'] . '/' . $field['field_name'],
danielebarchiesi@4 613 '#size' => $instance['widget']['settings']['size'],
danielebarchiesi@4 614 '#maxlength' => NULL,
danielebarchiesi@4 615 '#element_validate' => array('node_reference_autocomplete_validate'),
danielebarchiesi@4 616 '#value_callback' => 'node_reference_autocomplete_value',
danielebarchiesi@4 617 );
danielebarchiesi@4 618 break;
danielebarchiesi@4 619 }
danielebarchiesi@4 620
danielebarchiesi@4 621 return array('nid' => $element);
danielebarchiesi@4 622 }
danielebarchiesi@4 623
danielebarchiesi@4 624 /**
danielebarchiesi@4 625 * Value callback for a node_reference autocomplete element.
danielebarchiesi@4 626 *
danielebarchiesi@4 627 * Replace the node nid with a node title.
danielebarchiesi@4 628 */
danielebarchiesi@4 629 function node_reference_autocomplete_value($element, $input = FALSE, $form_state) {
danielebarchiesi@4 630 if ($input === FALSE) {
danielebarchiesi@4 631 // We're building the displayed 'default value': expand the raw nid into
danielebarchiesi@4 632 // "node title [nid:n]".
danielebarchiesi@4 633 $nid = $element['#default_value'];
danielebarchiesi@4 634 if (!empty($nid)) {
danielebarchiesi@4 635 $q = db_select('node', 'n');
danielebarchiesi@4 636 $node_title_alias = $q->addField('n', 'title');
danielebarchiesi@4 637 $q->addTag('node_access')
danielebarchiesi@4 638 ->condition('n.nid', $nid)
danielebarchiesi@4 639 ->range(0, 1);
danielebarchiesi@4 640 $result = $q->execute();
danielebarchiesi@4 641 // @todo If no result (node doesn't exist or no access).
danielebarchiesi@4 642 $value = $result->fetchField();
danielebarchiesi@4 643 $value .= ' [nid:' . $nid . ']';
danielebarchiesi@4 644 return $value;
danielebarchiesi@4 645 }
danielebarchiesi@4 646 }
danielebarchiesi@4 647 }
danielebarchiesi@4 648
danielebarchiesi@4 649 /**
danielebarchiesi@4 650 * Validation callback for a node_reference autocomplete element.
danielebarchiesi@4 651 */
danielebarchiesi@4 652 function node_reference_autocomplete_validate($element, &$form_state, $form) {
danielebarchiesi@4 653 $field = field_widget_field($element, $form_state);
danielebarchiesi@4 654 $instance = field_widget_instance($element, $form_state);
danielebarchiesi@4 655
danielebarchiesi@4 656 $value = $element['#value'];
danielebarchiesi@4 657 $nid = NULL;
danielebarchiesi@4 658
danielebarchiesi@4 659 if (!empty($value)) {
danielebarchiesi@4 660 // Check whether we have an explicit "[nid:n]" input.
danielebarchiesi@4 661 preg_match('/^(?:\s*|(.*) )?\[\s*nid\s*:\s*(\d+)\s*\]$/', $value, $matches);
danielebarchiesi@4 662 if (!empty($matches)) {
danielebarchiesi@4 663 // Explicit nid. Check that the 'title' part matches the actual title for
danielebarchiesi@4 664 // the nid.
danielebarchiesi@4 665 list(, $title, $nid) = $matches;
danielebarchiesi@4 666 if (!empty($title)) {
danielebarchiesi@4 667 $real_title = db_select('node', 'n')
danielebarchiesi@4 668 ->fields('n', array('title'))
danielebarchiesi@4 669 ->condition('n.nid', $nid)
danielebarchiesi@4 670 ->execute()
danielebarchiesi@4 671 ->fetchField();
danielebarchiesi@4 672 if (trim($title) != trim($real_title)) {
danielebarchiesi@4 673 form_error($element, t('%name: title mismatch. Please check your selection.', array('%name' => $instance['label'])));
danielebarchiesi@4 674 }
danielebarchiesi@4 675 }
danielebarchiesi@4 676 }
danielebarchiesi@4 677 else {
danielebarchiesi@4 678 // No explicit nid (the submitted value was not populated by autocomplete
danielebarchiesi@4 679 // selection). Get the nid of a referencable node from the entered title.
danielebarchiesi@4 680 $options = array(
danielebarchiesi@4 681 'string' => $value,
danielebarchiesi@4 682 'match' => 'equals',
danielebarchiesi@4 683 'limit' => 1,
danielebarchiesi@4 684 );
danielebarchiesi@4 685 $references = node_reference_potential_references($field, $options);
danielebarchiesi@4 686 if ($references) {
danielebarchiesi@4 687 // @todo The best thing would be to present the user with an
danielebarchiesi@4 688 // additional form, allowing the user to choose between valid
danielebarchiesi@4 689 // candidates with the same title. ATM, we pick the first
danielebarchiesi@4 690 // matching candidate...
danielebarchiesi@4 691 $nid = key($references);
danielebarchiesi@4 692 }
danielebarchiesi@4 693 else {
danielebarchiesi@4 694 form_error($element, t('%name: found no valid post with that title.', array('%name' => $instance['label'])));
danielebarchiesi@4 695 }
danielebarchiesi@4 696 }
danielebarchiesi@4 697 }
danielebarchiesi@4 698
danielebarchiesi@4 699 // Set the element's value as the node id that was extracted from the entered
danielebarchiesi@4 700 // input.
danielebarchiesi@4 701 form_set_value($element, $nid, $form_state);
danielebarchiesi@4 702 }
danielebarchiesi@4 703
danielebarchiesi@4 704 /**
danielebarchiesi@4 705 * Implements hook_field_widget_error().
danielebarchiesi@4 706 */
danielebarchiesi@4 707 function node_reference_field_widget_error($element, $error, $form, &$form_state) {
danielebarchiesi@4 708 form_error($element['nid'], $error['message']);
danielebarchiesi@4 709 }
danielebarchiesi@4 710
danielebarchiesi@4 711 /**
danielebarchiesi@4 712 * Builds a list of referenceable nodes suitable for the '#option' FAPI property.
danielebarchiesi@4 713 *
danielebarchiesi@4 714 * Warning: the function does NOT take care of encoding or escaping the node
danielebarchiesi@4 715 * titles. Proper massaging needs to be performed by the caller, according to
danielebarchiesi@4 716 * the destination FAPI '#type' (radios / checkboxes / select).
danielebarchiesi@4 717 *
danielebarchiesi@4 718 * @param $field
danielebarchiesi@4 719 * The field definition.
danielebarchiesi@4 720 * @param $flat
danielebarchiesi@4 721 * Whether optgroups are allowed.
danielebarchiesi@4 722 *
danielebarchiesi@4 723 * @return
danielebarchiesi@4 724 * An array of referenceable node titles, keyed by node id. If the $flat
danielebarchiesi@4 725 * parameter is TRUE, the list might be nested by optgroup first.
danielebarchiesi@4 726 */
danielebarchiesi@4 727 function _node_reference_options($field, $flat = TRUE) {
danielebarchiesi@4 728 $references = node_reference_potential_references($field);
danielebarchiesi@4 729
danielebarchiesi@4 730 $options = array();
danielebarchiesi@4 731 foreach ($references as $key => $value) {
danielebarchiesi@4 732 // The label, displayed in selects and checkboxes/radios, should have HTML
danielebarchiesi@4 733 // entities unencoded. The widgets (core's options.module) take care of
danielebarchiesi@4 734 // applying the relevant filters (strip_tags() or filter_xss()).
danielebarchiesi@4 735 $label = html_entity_decode($value['rendered'], ENT_QUOTES);
danielebarchiesi@4 736 if (empty($value['group']) || $flat) {
danielebarchiesi@4 737 $options[$key] = $label;
danielebarchiesi@4 738 }
danielebarchiesi@4 739 else {
danielebarchiesi@4 740 // The group name, displayed in selects, cannot contain tags, and should
danielebarchiesi@4 741 // have HTML entities unencoded.
danielebarchiesi@4 742 $group = html_entity_decode(strip_tags($value['group']), ENT_QUOTES);
danielebarchiesi@4 743 $options[$group][$key] = $label;
danielebarchiesi@4 744 }
danielebarchiesi@4 745 }
danielebarchiesi@4 746
danielebarchiesi@4 747 return $options;
danielebarchiesi@4 748 }
danielebarchiesi@4 749
danielebarchiesi@4 750 /**
danielebarchiesi@4 751 * Retrieves an array of candidate referenceable nodes.
danielebarchiesi@4 752 *
danielebarchiesi@4 753 * This info is used in various places (allowed values, autocomplete
danielebarchiesi@4 754 * results, input validation...). Some of them only need the nids,
danielebarchiesi@4 755 * others nid + titles, others yet nid + titles + rendered row (for
danielebarchiesi@4 756 * display in widgets).
danielebarchiesi@4 757 *
danielebarchiesi@4 758 * The array we return contains all the potentially needed information,
danielebarchiesi@4 759 * and lets consumers use the parts they actually need.
danielebarchiesi@4 760 *
danielebarchiesi@4 761 * @param $field
danielebarchiesi@4 762 * The field definition.
danielebarchiesi@4 763 * @param $options
danielebarchiesi@4 764 * An array of options to limit the scope of the returned list. The following
danielebarchiesi@4 765 * key/value pairs are accepted:
danielebarchiesi@4 766 * - string: string to filter titles on (used by autocomplete).
danielebarchiesi@4 767 * - match: operator to match the above string against, can be any of:
danielebarchiesi@4 768 * 'contains', 'equals', 'starts_with'. Defaults to 'contains'.
danielebarchiesi@4 769 * - ids: array of specific node ids to lookup.
danielebarchiesi@4 770 * - limit: maximum size of the the result set. Defaults to 0 (no limit).
danielebarchiesi@4 771 *
danielebarchiesi@4 772 * @return
danielebarchiesi@4 773 * An array of valid nodes in the form:
danielebarchiesi@4 774 * array(
danielebarchiesi@4 775 * nid => array(
danielebarchiesi@4 776 * 'title' => The node title,
danielebarchiesi@4 777 * 'rendered' => The text to display in widgets (can be HTML)
danielebarchiesi@4 778 * ),
danielebarchiesi@4 779 * ...
danielebarchiesi@4 780 * )
danielebarchiesi@4 781 */
danielebarchiesi@4 782 function node_reference_potential_references($field, $options = array()) {
danielebarchiesi@4 783 // Fill in default options.
danielebarchiesi@4 784 $options += array(
danielebarchiesi@4 785 'string' => '',
danielebarchiesi@4 786 'match' => 'contains',
danielebarchiesi@4 787 'ids' => array(),
danielebarchiesi@4 788 'limit' => 0,
danielebarchiesi@4 789 );
danielebarchiesi@4 790
danielebarchiesi@4 791 $results = &drupal_static(__FUNCTION__, array());
danielebarchiesi@4 792
danielebarchiesi@4 793 // Create unique id for static cache.
danielebarchiesi@4 794 $cid = $field['field_name'] . ':' . $options['match'] . ':'
danielebarchiesi@4 795 . ($options['string'] !== '' ? $options['string'] : implode('-', $options['ids']))
danielebarchiesi@4 796 . ':' . $options['limit'];
danielebarchiesi@4 797 if (!isset($results[$cid])) {
danielebarchiesi@4 798 $references = FALSE;
danielebarchiesi@4 799 if (module_exists('views') && !empty($field['settings']['view']['view_name'])) {
danielebarchiesi@4 800 $references = _node_reference_potential_references_views($field, $options);
danielebarchiesi@4 801 }
danielebarchiesi@4 802
danielebarchiesi@4 803 if ($references === FALSE) {
danielebarchiesi@4 804 $references = _node_reference_potential_references_standard($field, $options);
danielebarchiesi@4 805 }
danielebarchiesi@4 806
danielebarchiesi@4 807 // Store the results.
danielebarchiesi@4 808 $results[$cid] = !empty($references) ? $references : array();
danielebarchiesi@4 809 }
danielebarchiesi@4 810
danielebarchiesi@4 811 return $results[$cid];
danielebarchiesi@4 812 }
danielebarchiesi@4 813
danielebarchiesi@4 814 /**
danielebarchiesi@4 815 * Helper function for node_reference_potential_references().
danielebarchiesi@4 816 *
danielebarchiesi@4 817 * Case of Views-defined referenceable nodes.
danielebarchiesi@4 818 */
danielebarchiesi@4 819 function _node_reference_potential_references_views($field, $options) {
danielebarchiesi@4 820 $settings = $field['settings']['view'];
danielebarchiesi@4 821 $options['title_field'] = 'title';
danielebarchiesi@4 822 return references_potential_references_view('node', $settings['view_name'], $settings['display_name'], $settings['args'], $options);
danielebarchiesi@4 823 }
danielebarchiesi@4 824
danielebarchiesi@4 825 /**
danielebarchiesi@4 826 * Helper function for node_reference_potential_references().
danielebarchiesi@4 827 *
danielebarchiesi@4 828 * List of referenceable nodes defined by content types.
danielebarchiesi@4 829 */
danielebarchiesi@4 830 function _node_reference_potential_references_standard($field, $options) {
danielebarchiesi@4 831 // Avoid useless work
danielebarchiesi@4 832 if (!count($field['settings']['referenceable_types'])) {
danielebarchiesi@4 833 return array();
danielebarchiesi@4 834 }
danielebarchiesi@4 835
danielebarchiesi@4 836 $query = db_select('node', 'n');
danielebarchiesi@4 837 $node_nid_alias = $query->addField('n', 'nid');
danielebarchiesi@4 838 $node_title_alias = $query->addField('n', 'title', 'node_title');
danielebarchiesi@4 839 $node_type_alias = $query->addField('n', 'type', 'node_type');
danielebarchiesi@4 840 $query->addTag('node_access')
danielebarchiesi@4 841 ->addMetaData('id', ' _node_reference_potential_references_standard')
danielebarchiesi@4 842 ->addMetaData('field', $field)
danielebarchiesi@4 843 ->addMetaData('options', $options);
danielebarchiesi@4 844
danielebarchiesi@4 845 if (is_array($field['settings']['referenceable_types'])) {
danielebarchiesi@4 846 $query->condition('n.type', $field['settings']['referenceable_types'], 'IN');
danielebarchiesi@4 847 }
danielebarchiesi@4 848
danielebarchiesi@4 849 if ($options['string'] !== '') {
danielebarchiesi@4 850 switch ($options['match']) {
danielebarchiesi@4 851 case 'contains':
danielebarchiesi@4 852 $query->condition('n.title', '%' . $options['string'] . '%', 'LIKE');
danielebarchiesi@4 853 break;
danielebarchiesi@4 854
danielebarchiesi@4 855 case 'starts_with':
danielebarchiesi@4 856 $query->condition('n.title', $options['string'] . '%', 'LIKE');
danielebarchiesi@4 857 break;
danielebarchiesi@4 858
danielebarchiesi@4 859 case 'equals':
danielebarchiesi@4 860 default: // no match type or incorrect match type: use "="
danielebarchiesi@4 861 $query->condition('n.title', $options['string']);
danielebarchiesi@4 862 break;
danielebarchiesi@4 863 }
danielebarchiesi@4 864 }
danielebarchiesi@4 865
danielebarchiesi@4 866 if ($options['ids']) {
danielebarchiesi@4 867 $query->condition('n.nid', $options['ids'], 'IN');
danielebarchiesi@4 868 }
danielebarchiesi@4 869
danielebarchiesi@4 870 if ($options['limit']) {
danielebarchiesi@4 871 $query->range(0, $options['limit']);
danielebarchiesi@4 872 }
danielebarchiesi@4 873
danielebarchiesi@4 874 $query
danielebarchiesi@4 875 ->orderBy($node_title_alias)
danielebarchiesi@4 876 ->orderBy($node_type_alias);
danielebarchiesi@4 877
danielebarchiesi@4 878 $result = $query->execute()->fetchAll();
danielebarchiesi@4 879 $references = array();
danielebarchiesi@4 880 foreach ($result as $node) {
danielebarchiesi@4 881 $references[$node->nid] = array(
danielebarchiesi@4 882 'title' => $node->node_title,
danielebarchiesi@4 883 'rendered' => check_plain($node->node_title),
danielebarchiesi@4 884 );
danielebarchiesi@4 885 }
danielebarchiesi@4 886 return $references;
danielebarchiesi@4 887 }
danielebarchiesi@4 888
danielebarchiesi@4 889 /**
danielebarchiesi@4 890 * Menu callback for the autocomplete results.
danielebarchiesi@4 891 */
danielebarchiesi@4 892 function node_reference_autocomplete($entity_type, $bundle, $field_name, $string = '') {
danielebarchiesi@4 893 $field = field_info_field($field_name);
danielebarchiesi@4 894 $instance = field_info_instance($entity_type, $field_name, $bundle);
danielebarchiesi@4 895
danielebarchiesi@4 896 $options = array(
danielebarchiesi@4 897 'string' => $string,
danielebarchiesi@4 898 'match' => $instance['widget']['settings']['autocomplete_match'],
danielebarchiesi@4 899 'limit' => 10,
danielebarchiesi@4 900 );
danielebarchiesi@4 901 $references = node_reference_potential_references($field, $options);
danielebarchiesi@4 902
danielebarchiesi@4 903 $matches = array();
danielebarchiesi@4 904 foreach ($references as $id => $row) {
danielebarchiesi@4 905 // Markup is fine in autocompletion results (might happen when rendered
danielebarchiesi@4 906 // through Views) but we want to remove hyperlinks.
danielebarchiesi@4 907 $suggestion = preg_replace('/<a href="([^<]*)">([^<]*)<\/a>/', '$2', $row['rendered']);
danielebarchiesi@4 908 // Add a class wrapper for a few required CSS overrides.
danielebarchiesi@4 909 $matches[$row['title'] . " [nid:$id]"] = '<div class="reference-autocomplete">' . $suggestion . '</div>';
danielebarchiesi@4 910 }
danielebarchiesi@4 911
danielebarchiesi@4 912 drupal_json_output($matches);
danielebarchiesi@4 913 }
danielebarchiesi@4 914
danielebarchiesi@4 915 /**
danielebarchiesi@4 916 * Implements hook_node_type_update().
danielebarchiesi@4 917 *
danielebarchiesi@4 918 * Reflect type name changes to the 'referenceable types' settings: when
danielebarchiesi@4 919 * the name of a type changes, the change needs to be reflected in the
danielebarchiesi@4 920 * "referenceable types" setting for any node_reference field
danielebarchiesi@4 921 * referencing it.
danielebarchiesi@4 922 */
danielebarchiesi@4 923 function node_reference_node_type_update($info) {
danielebarchiesi@4 924 if (!empty($info->old_type) && $info->old_type != $info->type) {
danielebarchiesi@4 925 $fields = field_info_fields();
danielebarchiesi@4 926 foreach ($fields as $field_name => $field) {
danielebarchiesi@4 927 if ($field['type'] == 'node_reference' && isset($field['settings']['referenceable_types'][$info->old_type])) {
danielebarchiesi@4 928 $field['settings']['referenceable_types'][$info->type] = empty($field['settings']['referenceable_types'][$info->old_type]) ? 0 : $info->type;
danielebarchiesi@4 929 unset($field['settings']['referenceable_types'][$info->old_type]);
danielebarchiesi@4 930 field_update_field($field);
danielebarchiesi@4 931 }
danielebarchiesi@4 932 }
danielebarchiesi@4 933 }
danielebarchiesi@4 934 }
danielebarchiesi@4 935
danielebarchiesi@4 936 /**
danielebarchiesi@4 937 * Theme preprocess function.
danielebarchiesi@4 938 *
danielebarchiesi@4 939 * Allows specific node templates for nodes displayed as values of a
danielebarchiesi@4 940 * node_reference field with a specific view mode.
danielebarchiesi@4 941 */
danielebarchiesi@4 942 function node_reference_preprocess_node(&$vars) {
danielebarchiesi@4 943 // The 'referencing_field' attribute of the node is added by the
danielebarchiesi@4 944 // node_reference_node mode formatter (display referenced node
danielebarchiesi@4 945 // in a specific view mode).
danielebarchiesi@4 946 if (!empty($vars['node']->referencing_field)) {
danielebarchiesi@4 947 $node = $vars['node'];
danielebarchiesi@4 948 $field_name = $node->referencing_field;
danielebarchiesi@4 949 $vars['theme_hook_suggestions'][] = 'node__node_reference';
danielebarchiesi@4 950 $vars['theme_hook_suggestions'][] = 'node__node_reference__' . $field_name;
danielebarchiesi@4 951 $vars['theme_hook_suggestions'][] = 'node__node_reference__' . $node->type;
danielebarchiesi@4 952 $vars['theme_hook_suggestions'][] = 'node__node_reference__' . $field_name . '__' . $node->type;
danielebarchiesi@4 953 }
danielebarchiesi@4 954 }
danielebarchiesi@4 955
danielebarchiesi@4 956 /**
danielebarchiesi@4 957 * Implements hook_field_prepare_translation().
danielebarchiesi@4 958 *
danielebarchiesi@4 959 * When preparing a translation, load any translations of existing
danielebarchiesi@4 960 * references.
danielebarchiesi@4 961 */
danielebarchiesi@4 962 function node_reference_field_prepare_translation($entity_type, $entity, $field, $instance, $langcode, &$items, $source_entity, $source_langcode) {
danielebarchiesi@4 963 if (isset($items) && is_array($items)) {
danielebarchiesi@4 964 // Match each reference with its matching translation, if it exists.
danielebarchiesi@4 965 foreach ($items as $key => $item) {
danielebarchiesi@4 966 $reference_node = node_load($item['nid']);
danielebarchiesi@4 967 $items[$key]['nid'] = node_reference_find_translation($reference_node, $entity->language);
danielebarchiesi@4 968 }
danielebarchiesi@4 969 }
danielebarchiesi@4 970 }
danielebarchiesi@4 971
danielebarchiesi@4 972 /**
danielebarchiesi@4 973 * Find a translation for a specific node reference, if it exists.
danielebarchiesi@4 974 *
danielebarchiesi@4 975 * @param $reference_node
danielebarchiesi@4 976 * The untranslated node reference.
danielebarchiesi@4 977 * @param $langcode
danielebarchiesi@4 978 *
danielebarchiesi@4 979 * @return
danielebarchiesi@4 980 * A nid for the translation of the node reference,
danielebarchiesi@4 981 * otherwise the original untranslated nid if no translation exists.
danielebarchiesi@4 982 */
danielebarchiesi@4 983 function node_reference_find_translation($reference_node, $langcode) {
danielebarchiesi@4 984 // Check if the source node translation is set and if translations are supported.
danielebarchiesi@4 985 if (isset($reference_node->tnid) && translation_supported_type($reference_node->type)) {
danielebarchiesi@4 986 // Determine whether an alternative language is being used.
danielebarchiesi@4 987 if (!empty($reference_node->language) && $reference_node->language != $langcode) {
danielebarchiesi@4 988 // Return a corresponding translation nid for the reference (if it exists).
danielebarchiesi@4 989 $translations = translation_node_get_translations($reference_node->tnid);
danielebarchiesi@4 990 if (isset($translations[$langcode])) {
danielebarchiesi@4 991 return $translations[$langcode]->nid;
danielebarchiesi@4 992 }
danielebarchiesi@4 993 }
danielebarchiesi@4 994 }
danielebarchiesi@4 995 // Return the untranslated reference nid, no matching translations found.
danielebarchiesi@4 996 return $reference_node->nid;
danielebarchiesi@4 997 }
danielebarchiesi@4 998
danielebarchiesi@4 999 /**
danielebarchiesi@4 1000 * Implements hook_options_list().
danielebarchiesi@4 1001 */
danielebarchiesi@4 1002 function node_reference_options_list($field) {
danielebarchiesi@4 1003 return _node_reference_options($field, FALSE);
danielebarchiesi@4 1004 }
danielebarchiesi@4 1005
danielebarchiesi@4 1006 /**
danielebarchiesi@4 1007 * Implements hook_content_migrate_field_alter().
danielebarchiesi@4 1008 *
danielebarchiesi@4 1009 * Use this to tweak the conversion of field settings from the D6 style to the
danielebarchiesi@4 1010 * D7 style for specific situations not handled by basic conversion, as when
danielebarchiesi@4 1011 * field types or settings are changed.
danielebarchiesi@4 1012 *
danielebarchiesi@4 1013 * $field_value['widget_type'] is available to
danielebarchiesi@4 1014 * see what widget type was originally used.
danielebarchiesi@4 1015 */
danielebarchiesi@4 1016 function node_reference_content_migrate_field_alter(&$field_value, $instance_value) {
danielebarchiesi@4 1017 switch ($field_value['module']) {
danielebarchiesi@4 1018 case 'nodereference':
danielebarchiesi@4 1019 $field_value['module'] = 'node_reference';
danielebarchiesi@4 1020 $field_value['type'] = 'node_reference';
danielebarchiesi@4 1021
danielebarchiesi@4 1022 // Translate 'view' settings.
danielebarchiesi@4 1023 $view_name = isset($field_value['settings']['advanced_view']) ? $field_value['settings']['advanced_view'] : '';
danielebarchiesi@4 1024 $view_args = isset($field_value['settings']['advanced_view_args']) ? $field_value['settings']['advanced_view_args'] : '';
danielebarchiesi@4 1025 $view_args = array_map('trim', explode(',', $view_args));
danielebarchiesi@4 1026 $field_value['settings']['view'] = array(
danielebarchiesi@4 1027 'view_name' => $view_name,
danielebarchiesi@4 1028 'display_name' => 'default',
danielebarchiesi@4 1029 'args' => $view_args,
danielebarchiesi@4 1030 );
danielebarchiesi@4 1031 if ($view_name) {
danielebarchiesi@4 1032 $field_value['messages'][] = t("The field uses the view @view_name to determine referenceable nodes. You will need to manually edit the view and add a display of type 'References'.", array('@view_name' => $view_name));
danielebarchiesi@4 1033 }
danielebarchiesi@4 1034 unset($field_value['settings']['advanced_view']);
danielebarchiesi@4 1035 unset($field_value['settings']['advanced_view_args']);
danielebarchiesi@4 1036
danielebarchiesi@4 1037 break;
danielebarchiesi@4 1038 }
danielebarchiesi@4 1039 }
danielebarchiesi@4 1040
danielebarchiesi@4 1041 /**
danielebarchiesi@4 1042 * Implements hook_content_migrate_instance_alter().
danielebarchiesi@4 1043 *
danielebarchiesi@4 1044 * Use this to tweak the conversion of instance or widget settings from the D6
danielebarchiesi@4 1045 * style to the D7 style for specific situations not handled by basic
danielebarchiesi@4 1046 * conversion, as when formatter or widget names or settings are changed.
danielebarchiesi@4 1047 */
danielebarchiesi@4 1048 function node_reference_content_migrate_instance_alter(&$instance_value, $field_value) {
danielebarchiesi@4 1049 switch ($field_value['type']) {
danielebarchiesi@4 1050 case 'nodereference':
danielebarchiesi@4 1051 // Massage formatters.
danielebarchiesi@4 1052 foreach ($instance_value['display'] as $context => &$display) {
danielebarchiesi@4 1053 switch ($display['type']) {
danielebarchiesi@4 1054 case 'full':
danielebarchiesi@4 1055 case 'teaser':
danielebarchiesi@4 1056 // Those two formatters have been merged into
danielebarchiesi@4 1057 // 'node_reference_view_mode', with a formatter setting.
danielebarchiesi@4 1058 $display['type'] = 'node_reference_node';
danielebarchiesi@4 1059 $display['settings']['node_reference_view_mode'] = $display['type'];
danielebarchiesi@4 1060 break;
danielebarchiesi@4 1061
danielebarchiesi@4 1062 default:
danielebarchiesi@4 1063 // The formatter names changed, all are prefixed with
danielebarchiesi@4 1064 // 'node_reference_'.
danielebarchiesi@4 1065 $display['type'] = 'node_reference_' . $display['type'];
danielebarchiesi@4 1066 break;
danielebarchiesi@4 1067 }
danielebarchiesi@4 1068 }
danielebarchiesi@4 1069 // Massage the widget.
danielebarchiesi@4 1070 switch ($instance_value['widget']['type']) {
danielebarchiesi@4 1071 case 'nodereference_autocomplete':
danielebarchiesi@4 1072 $instance_value['widget']['type'] = 'node_reference_autocomplete';
danielebarchiesi@4 1073 $instance_value['widget']['module'] = 'node_reference';
danielebarchiesi@4 1074 break;
danielebarchiesi@4 1075 case 'nodereference_select':
danielebarchiesi@4 1076 $instance_value['widget']['type'] = 'options_select';
danielebarchiesi@4 1077 $instance_value['widget']['module'] = 'options';
danielebarchiesi@4 1078 break;
danielebarchiesi@4 1079 case 'nodereference_buttons':
danielebarchiesi@4 1080 $instance_value['widget']['type'] = 'options_buttons';
danielebarchiesi@4 1081 $instance_value['widget']['module'] = 'options';
danielebarchiesi@4 1082 }
danielebarchiesi@4 1083 break;
danielebarchiesi@4 1084 }
danielebarchiesi@4 1085 }
danielebarchiesi@4 1086
danielebarchiesi@4 1087 /**
danielebarchiesi@4 1088 * Implements hook_field_views_data().
danielebarchiesi@4 1089 *
danielebarchiesi@4 1090 * In addition to the default field information we add the relationship for
danielebarchiesi@4 1091 * views to connect back to the node table.
danielebarchiesi@4 1092 */
danielebarchiesi@4 1093 function node_reference_field_views_data($field) {
danielebarchiesi@4 1094 // No module_load_include(): this hook is invoked from
danielebarchiesi@4 1095 // views/modules/field.views.inc, which is where that function is defined.
danielebarchiesi@4 1096 $data = field_views_field_default_views_data($field);
danielebarchiesi@4 1097
danielebarchiesi@4 1098 $storage = $field['storage']['details']['sql'];
danielebarchiesi@4 1099
danielebarchiesi@4 1100 foreach ($storage as $age => $table_data) {
danielebarchiesi@4 1101 $table = key($table_data);
danielebarchiesi@4 1102 $columns = current($table_data);
danielebarchiesi@4 1103 $id_column = $columns['nid'];
danielebarchiesi@4 1104 if (isset($data[$table])) {
danielebarchiesi@4 1105 // Filter: swap the handler to the 'in' operator. The callback receives
danielebarchiesi@4 1106 // the field name instead of the whole $field structure to keep views
danielebarchiesi@4 1107 // data to a reasonable size.
danielebarchiesi@4 1108 $data[$table][$id_column]['filter']['handler'] = 'views_handler_filter_in_operator';
danielebarchiesi@4 1109 $data[$table][$id_column]['filter']['options callback'] = 'node_reference_views_filter_options';
danielebarchiesi@4 1110 $data[$table][$id_column]['filter']['options arguments'] = array($field['field_name']);
danielebarchiesi@4 1111
danielebarchiesi@4 1112 // Argument: display node.title in argument titles (handled in our custom
danielebarchiesi@4 1113 // handler) and summary lists (handled by the base views_handler_argument
danielebarchiesi@4 1114 // handler).
danielebarchiesi@4 1115 // Both mechanisms rely on the 'name table' and 'name field' information
danielebarchiesi@4 1116 // below, by joining to a separate copy of the base table from the field
danielebarchiesi@4 1117 // data table.
danielebarchiesi@4 1118 $data[$table][$id_column]['argument']['handler'] = 'references_handler_argument';
danielebarchiesi@4 1119 $data[$table][$id_column]['argument']['name table'] = $table . '_reference';
danielebarchiesi@4 1120 $data[$table][$id_column]['argument']['name field'] = 'title';
danielebarchiesi@4 1121 $data[$table . '_reference']['table']['join'][$table] = array(
danielebarchiesi@4 1122 'left_field' => $id_column,
danielebarchiesi@4 1123 'table' => 'node',
danielebarchiesi@4 1124 'field' => 'nid',
danielebarchiesi@4 1125 );
danielebarchiesi@4 1126
danielebarchiesi@4 1127 // Relationship.
danielebarchiesi@4 1128 $data[$table][$id_column]['relationship'] = array(
danielebarchiesi@4 1129 'handler' => 'references_handler_relationship',
danielebarchiesi@4 1130 'base' => 'node',
danielebarchiesi@4 1131 'base field' => 'nid',
danielebarchiesi@4 1132 'field' => $id_column,
danielebarchiesi@4 1133 'label' => $field['field_name'],
danielebarchiesi@4 1134 'field_name' => $field['field_name'],
danielebarchiesi@4 1135 );
danielebarchiesi@4 1136 }
danielebarchiesi@4 1137 }
danielebarchiesi@4 1138
danielebarchiesi@4 1139 return $data;
danielebarchiesi@4 1140 }
danielebarchiesi@4 1141
danielebarchiesi@4 1142 /**
danielebarchiesi@4 1143 * Implements hook_field_views_data_views_data_alter().
danielebarchiesi@4 1144 */
danielebarchiesi@4 1145 function node_reference_field_views_data_views_data_alter(&$data, $field) {
danielebarchiesi@4 1146 foreach ($field['bundles'] as $entity_type => $bundles) {
danielebarchiesi@4 1147 $entity_info = entity_get_info($entity_type);
danielebarchiesi@4 1148 $pseudo_field_name = 'reverse_' . $field['field_name'] . '_' . $entity_type;
danielebarchiesi@4 1149
danielebarchiesi@4 1150 list($label, $all_labels) = field_views_field_label($field['field_name']);
danielebarchiesi@4 1151 $entity = $entity_info['label'];
danielebarchiesi@4 1152 if ($entity == t('Node')) {
danielebarchiesi@4 1153 $entity = t('Content');
danielebarchiesi@4 1154 }
danielebarchiesi@4 1155
danielebarchiesi@4 1156 // Only specify target entity type if the field is used in more than one.
danielebarchiesi@4 1157 if (count($field['bundles']) > 1) {
danielebarchiesi@4 1158 $title = t('@field (@field_name) - reverse (to @entity)', array('@entity' => $entity, '@field' => $label, '@field_name' => $field['field_name']));
danielebarchiesi@4 1159 }
danielebarchiesi@4 1160 else {
danielebarchiesi@4 1161 $title = t('@field (@field_name) - reverse', array('@entity' => $entity, '@field' => $label, '@field_name' => $field['field_name']));
danielebarchiesi@4 1162 }
danielebarchiesi@4 1163 $data['node'][$pseudo_field_name]['relationship'] = array(
danielebarchiesi@4 1164 'title' => $title,
danielebarchiesi@4 1165 'help' => t('Relate each @entity referencing the node through @field.', array('@entity' => $entity, '@field' => $label)),
danielebarchiesi@4 1166 'handler' => 'views_handler_relationship_entity_reverse',
danielebarchiesi@4 1167 'field_name' => $field['field_name'],
danielebarchiesi@4 1168 'field table' => _field_sql_storage_tablename($field),
danielebarchiesi@4 1169 'field field' => $field['field_name'] . '_nid',
danielebarchiesi@4 1170 'base' => $entity_info['base table'],
danielebarchiesi@4 1171 'base field' => $entity_info['entity keys']['id'],
danielebarchiesi@4 1172 'label' => t('!field_name', array('!field_name' => $field['field_name'])),
danielebarchiesi@4 1173 );
danielebarchiesi@4 1174 }
danielebarchiesi@4 1175 }
danielebarchiesi@4 1176
danielebarchiesi@4 1177 /**
danielebarchiesi@4 1178 * 'options callback' for the views_handler_filter_in_operator filter.
danielebarchiesi@4 1179 *
danielebarchiesi@4 1180 * @param $field_name
danielebarchiesi@4 1181 * The field name.
danielebarchiesi@4 1182 */
danielebarchiesi@4 1183 function node_reference_views_filter_options($field_name) {
danielebarchiesi@4 1184 $options = array();
danielebarchiesi@4 1185
danielebarchiesi@4 1186 if ($field = field_info_field($field_name)) {
danielebarchiesi@4 1187 $options = _node_reference_options($field, TRUE);
danielebarchiesi@4 1188
danielebarchiesi@4 1189 // The options are displayed in checkboxes within the filter admin form, and
danielebarchiesi@4 1190 // in a select within an exposed filter. Checkboxes accept HTML, other
danielebarchiesi@4 1191 // entities should be encoded; selects require the exact opposite: no HTML,
danielebarchiesi@4 1192 // no encoding. We go for a middle ground: strip tags, leave entities
danielebarchiesi@4 1193 // unencoded.
danielebarchiesi@4 1194 foreach ($options as $key => $value) {
danielebarchiesi@4 1195 $options[$key] = strip_tags($value);
danielebarchiesi@4 1196 }
danielebarchiesi@4 1197 }
danielebarchiesi@4 1198
danielebarchiesi@4 1199 return $options;
danielebarchiesi@4 1200 }