entity_reference.module 9.1 KB
Newer Older
1
2
3
4
5
6
7
8
9
<?php

/**
 * @file
 * Provides a field that can reference other entities.
 */

use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Database\Query\AlterableInterface;
10
use Drupal\Core\Form\FormStateInterface;
11
use Drupal\Core\Render\Element;
12
use Drupal\Core\Routing\RouteMatchInterface;
13
use Drupal\field\Entity\FieldStorageConfig;
14
use Drupal\field\Entity\FieldConfig;
15
use Drupal\field\FieldStorageConfigInterface;
16

17
18
19
/**
 * Implements hook_help().
 */
20
function entity_reference_help($route_name, RouteMatchInterface $route_match) {
21
22
  switch ($route_name) {
    case 'help.page.entity_reference':
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
      $output = '';
      $output .= '<h3>' . t('About') . '</h3>';
      $output .= '<p>' . t('The Entity Reference module allows you to create fields that contain links to other entities (such as content items, taxonomy terms, etc.) within the site. This allows you, for example, to include a link to a user within a content item. For more information, see <a href="!er_do">the online documentation for the Entity Reference module</a>, the <a href="!entity_help">Entity module help page</a>, and the <a href="!field_help">Field module help page</a>.', array('!field_help' => \Drupal::url('help.page', array('name' => 'field')),'!entity_help' => \Drupal::url('help.page', array('name' => 'entity')), '!er_do' => 'https://drupal.org/documentation/modules/entityreference')) . '</p>';
      $output .= '<h3>' . t('Uses') . '</h3>';
      $output .= '<dl>';
      $output .= '<dt>' . t('Managing and displaying entity reference fields') . '</dt>';
      $output .= '<dd>' . t('The <em>settings</em> and the <em>display</em> of the entity reference field can be configured separately. See the <a href="!field_ui">Field UI help</a> for more information on how to manage fields and their display.', array('!field_ui' => \Drupal::url('help.page', array('name' => 'field_ui')))) . '</dd>';
      $output .= '<dt>' . t('Selecting reference type') . '</dt>';
      $output .= '<dd>' . t('In the field settings you can select which entity type you want to create a reference to.') . '</dd>';
      $output .= '<dt>' . t('Filtering and sorting reference fields') . '</dt>';
      $output .= '<dd>' . t('Depending on the chosen entity type, additional filtering and sorting options are available for the list of entities that can be referred to, in the field settings. For example, the list of users can be filtered by role and sorted by name or ID.') . '</dd>';
      $output .= '<dt>' . t('Displaying a reference') . '</dt>';
      $output .= '<dd>' . t('An entity reference can be displayed as a simple label with or without a link to the entity. Alternatively, the referenced entity can be displayed as a teaser (or any other available view mode) inside the referencing entity.') . '</dd>';
      $output .= '</dl>';
      return $output;
  }
}

41
/**
42
 * Implements hook_field_info_alter().
43
 */
44
function entity_reference_field_info_alter(&$info) {
45
  // Make the entity reference field configurable.
46
  $info['entity_reference']['no_ui'] = FALSE;
47
  $info['entity_reference']['class'] = '\Drupal\entity_reference\ConfigurableEntityReferenceItem';
48
  $info['entity_reference']['list_class'] = '\Drupal\Core\Field\EntityReferenceFieldItemList';
49
50
  $info['entity_reference']['default_widget'] = 'entity_reference_autocomplete';
  $info['entity_reference']['default_formatter'] = 'entity_reference_label';
51
  $info['entity_reference']['provider'] = 'entity_reference';
52
53
}

54
55
56
57
58
59
60
61
62
63
64
65
/**
 * Implements hook_field_widget_info_alter().
 */
function entity_reference_field_widget_info_alter(&$info) {
  if (isset($info['options_select'])) {
    $info['options_select']['field_types'][] = 'entity_reference';
  }
  if (isset($info['options_buttons'])) {
    $info['options_buttons']['field_types'][] = 'entity_reference';
  }
}

66
/**
67
 * Implements hook_ENTITY_TYPE_update() for 'field_storage_config'.
68
69
70
 *
 * Reset the instance handler settings, when the target type is changed.
 */
71
72
function entity_reference_field_storage_config_update(FieldStorageConfigInterface $field_storage) {
  if ($field_storage->type != 'entity_reference') {
73
    // Only act on entity reference fields.
74
75
76
    return;
  }

77
  if ($field_storage->isSyncing()) {
78
79
80
81
    // Don't change anything during a configuration sync.
    return;
  }

82
  if ($field_storage->getSetting('target_type') == $field_storage->original->getSetting('target_type')) {
83
84
85
86
    // Target type didn't change.
    return;
  }

87
  if (empty($field_storage->bundles)) {
88
    // Field storage has no fields.
89
90
91
    return;
  }

92
  $field_name = $field_storage->getName();
93

94
  foreach ($field_storage->bundles() as $entity_type => $bundles) {
95
    foreach ($bundles as $bundle) {
96
97
98
      $field = FieldConfig::loadByName($entity_type, $bundle, $field_name);
      $field->settings['handler_settings'] = array();
      $field->save();
99
100
101
102
103
    }
  }
}

/**
104
105
 * Render API callback: Processes the field settings form and allows access to
 * the form state.
106
 *
107
 * @see entity_reference_field_field_settings_form()
108
 */
109
110
function _entity_reference_field_field_settings_ajax_process($form, FormStateInterface $form_state) {
  _entity_reference_field_field_settings_ajax_process_element($form, $form);
111
112
113
114
115
  return $form;
}

/**
 * Adds entity_reference specific properties to AJAX form elements from the
116
 * field settings form.
117
 *
118
 * @see _entity_reference_field_field_settings_ajax_process()
119
 */
120
function _entity_reference_field_field_settings_ajax_process_element(&$element, $main_form) {
121
122
123
124
125
126
127
128
  if (!empty($element['#ajax'])) {
    $element['#ajax'] = array(
      'callback' => 'entity_reference_settings_ajax',
      'wrapper' => $main_form['#id'],
      'element' => $main_form['#array_parents'],
    );
  }

129
  foreach (Element::children($element) as $key) {
130
    _entity_reference_field_field_settings_ajax_process_element($element[$key], $main_form);
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
  }
}

/**
 * Render API callback: Moves entity_reference specific Form API elements
 * (i.e. 'handler_settings') up a level for easier processing by the validation
 * and submission handlers.
 *
 * @see _entity_reference_field_settings_process()
 */
function _entity_reference_form_process_merge_parent($element) {
  $parents = $element['#parents'];
  array_pop($parents);
  $element['#parents'] = $parents;
  return $element;
}

/**
 * Form element validation handler; Filters the #value property of an element.
 */
151
function _entity_reference_element_validate_filter(&$element, FormStateInterface $form_state) {
152
153
154
155
156
157
158
  $element['#value'] = array_filter($element['#value']);
  form_set_value($element, $element['#value'], $form_state);
}

/**
 * Ajax callback for the handler settings form.
 *
159
 * @see entity_reference_field_field_settings_form()
160
 */
161
function entity_reference_settings_ajax($form, FormStateInterface $form_state) {
162
  return NestedArray::getValue($form, $form_state->getTriggeringElement()['#ajax']['element']);
163
164
165
166
167
}

/**
 * Submit handler for the non-JS case.
 *
168
 * @see entity_reference_field_field_settings_form()
169
 */
170
function entity_reference_settings_ajax_submit($form, FormStateInterface $form_state) {
171
  $form_state->setRebuild();
172
173
174
175
176
177
178
179
180
181
}

/**
 * Implements hook_query_TAG_alter().
 */
function entity_reference_query_entity_reference_alter(AlterableInterface $query) {
  $handler = $query->getMetadata('entity_reference_selection_handler');
  $handler->entityQueryAlter($query);
}

182
/**
183
 * Creates a field of an entity reference field storage on the specified bundle.
184
185
 *
 * @param string $entity_type
186
 *   The type of entity the field will be attached to.
187
 * @param string $bundle
188
 *   The bundle name of the entity the field will be attached to.
189
190
191
192
 * @param string $field_name
 *   The name of the field; if it already exists, a new instance of the existing
 *   field will be created.
 * @param string $field_label
193
 *   The label of the field.
194
195
196
197
198
199
200
 * @param string $target_entity_type
 *   The type of the referenced entity.
 * @param string $selection_handler
 *   The selection handler used by this field.
 * @param array $selection_handler_settings
 *   An array of settings supported by the selection handler specified above.
 *   (e.g. 'target_bundles', 'sort', 'auto_create', etc).
201
202
 * @param int $cardinality
 *   The cardinality of the field.
203
204
205
 *
 * @see \Drupal\entity_reference\Plugin\entity_reference\selection\SelectionBase::settingsForm()
 */
206
function entity_reference_create_field($entity_type, $bundle, $field_name, $field_label, $target_entity_type, $selection_handler = 'default', $selection_handler_settings = array(), $cardinality = 1) {
207
  // Look for or add the specified field to the requested entity bundle.
208
209
210
  if (!FieldStorageConfig::loadByName($entity_type, $field_name)) {
    entity_create('field_storage_config', array(
      'field_name' => $field_name,
211
      'type' => 'entity_reference',
212
      'entity_type' => $entity_type,
213
      'cardinality' => $cardinality,
214
215
216
      'settings' => array(
        'target_type' => $target_entity_type,
      ),
217
    ))->save();
218
  }
219
220
  if (!FieldConfig::loadByName($entity_type, $bundle, $field_name)) {
    entity_create('field_config', array(
221
222
223
224
225
226
227
228
      'field_name' => $field_name,
      'entity_type' => $entity_type,
      'bundle' => $bundle,
      'label' => $field_label,
      'settings' => array(
        'handler' => $selection_handler,
        'handler_settings' => $selection_handler_settings,
      ),
229
    ))->save();
230
231
  }
}
232