Issue #2429191 by claudiu.cristea, amateescu, yched, nlisgo, Berdir, alexpott, klausi, Wim Leers, xjm, catch: Deprecate entity_reference.module and move its functionality to core

8.0.x
Alex Pott 2015-10-06 12:02:22 +01:00
parent 02bd75b1e8
commit 97823b5a54
115 changed files with 1422 additions and 1017 deletions

View File

@ -323,10 +323,6 @@ Email module
Editor module
- Wim Leers 'Wim Leers' https://www.drupal.org/u/wim-leers
Entity Reference module
- Amitai Burstein 'Amitaibu' https://www.drupal.org/u/amitaibu
- Andrei Mateescu 'amateescu' https://www.drupal.org/u/amateescu
Field UI module
- Yves Chedemois 'yched' https://www.drupal.org/u/yched
- Kristof De Jaeger 'swentel' https://www.drupal.org/u/swentel

View File

@ -12,6 +12,7 @@ use Drupal\Core\Database\Query\AlterableInterface;
use Drupal\Core\Database\Query\SelectInterface;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Entity\EntityReferenceSelection\SelectionInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
@ -135,7 +136,7 @@ class DefaultSelection extends PluginBase implements SelectionInterface, Contain
'#required' => TRUE,
'#size' => 6,
'#multiple' => TRUE,
'#element_validate' => array('_entity_reference_element_validate_filter'),
'#element_validate' => [[get_class($this), 'elementValidateFilter']],
);
}
else {
@ -182,7 +183,7 @@ class DefaultSelection extends PluginBase implements SelectionInterface, Contain
$form['sort']['settings'] = array(
'#type' => 'container',
'#attributes' => array('class' => array('entity_reference-settings')),
'#process' => array('_entity_reference_form_process_merge_parent'),
'#process' => [[EntityReferenceItem::class, 'formProcessMergeParent']],
);
if ($selection_handler_settings['sort']['field'] != '_none') {
@ -225,6 +226,14 @@ class DefaultSelection extends PluginBase implements SelectionInterface, Contain
*/
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { }
/**
* Form element validation handler; Filters the #value property of an element.
*/
public static function elementValidateFilter(&$element, FormStateInterface $form_state) {
$element['#value'] = array_filter($element['#value']);
$form_state->setValueForElement($element, $element['#value']);
}
/**
* {@inheritdoc}
*/
@ -320,8 +329,7 @@ class DefaultSelection extends PluginBase implements SelectionInterface, Contain
// Add entity-access tag.
$query->addTag($target_type . '_access');
// Add the Selection handler for
// entity_reference_query_entity_reference_alter().
// Add the Selection handler for system_query_entity_reference_alter().
$query->addTag('entity_reference');
$query->addMetaData('entity_reference_selection_handler', $this);

View File

@ -7,15 +7,24 @@
namespace Drupal\Core\Field\Plugin\Field\FieldType;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\TypedData\EntityDataDefinition;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemBase;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Field\PreconfiguredFieldUiOptionsInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Form\OptGroup;
use Drupal\Core\Render\Element;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\TypedData\DataReferenceDefinition;
use Drupal\Core\TypedData\DataReferenceTargetDefinition;
use Drupal\Core\TypedData\OptionsProviderInterface;
use Drupal\Core\Validation\Plugin\Validation\Constraint\AllowedValuesConstraint;
/**
* Defines the 'entity_reference' entity field type.
@ -28,14 +37,15 @@ use Drupal\Core\TypedData\DataReferenceTargetDefinition;
* label = @Translation("Entity reference"),
* description = @Translation("An entity field containing an entity reference."),
* category = @Translation("Reference"),
* no_ui = TRUE,
* default_widget = "entity_reference_autocomplete",
* default_formatter = "entity_reference_label",
* list_class = "\Drupal\Core\Field\EntityReferenceFieldItemList",
* default_widget = "entity_reference_autocomplete",
* default_formatter = "entity_reference_label",
* constraints = {"ValidReference" = {}}
* )
*/
class EntityReferenceItem extends FieldItemBase {
class EntityReferenceItem extends FieldItemBase implements OptionsProviderInterface, PreconfiguredFieldUiOptionsInterface {
/**
* {@inheritdoc}
@ -148,6 +158,13 @@ class EntityReferenceItem extends FieldItemBase {
*/
public function getConstraints() {
$constraints = parent::getConstraints();
// Remove the 'AllowedValuesConstraint' validation constraint because entity
// reference fields already use the 'ValidReference' constraint.
foreach ($constraints as $key => $constraint) {
if ($constraint instanceof AllowedValuesConstraint) {
unset($constraints[$key]);
}
}
list($current_handler) = explode(':', $this->getSetting('handler'), 2);
if ($current_handler === 'default') {
$handler_settings = $this->getSetting('handler_settings');
@ -280,6 +297,103 @@ class EntityReferenceItem extends FieldItemBase {
}
}
/**
* {@inheritdoc}
*/
public function storageSettingsForm(array &$form, FormStateInterface $form_state, $has_data) {
$element['target_type'] = array(
'#type' => 'select',
'#title' => t('Type of item to reference'),
'#options' => \Drupal::entityManager()->getEntityTypeLabels(TRUE),
'#default_value' => $this->getSetting('target_type'),
'#required' => TRUE,
'#disabled' => $has_data,
'#size' => 1,
);
return $element;
}
/**
* {@inheritdoc}
*/
public function fieldSettingsForm(array $form, FormStateInterface $form_state) {
$field = $form_state->getFormObject()->getEntity();
// Get all selection plugins for this entity type.
$selection_plugins = \Drupal::service('plugin.manager.entity_reference_selection')->getSelectionGroups($this->getSetting('target_type'));
$handlers_options = array();
foreach (array_keys($selection_plugins) as $selection_group_id) {
// We only display base plugins (e.g. 'default', 'views', ...) and not
// entity type specific plugins (e.g. 'default:node', 'default:user',
// ...).
if (array_key_exists($selection_group_id, $selection_plugins[$selection_group_id])) {
$handlers_options[$selection_group_id] = Html::escape($selection_plugins[$selection_group_id][$selection_group_id]['label']);
}
elseif (array_key_exists($selection_group_id . ':' . $this->getSetting('target_type'), $selection_plugins[$selection_group_id])) {
$selection_group_plugin = $selection_group_id . ':' . $this->getSetting('target_type');
$handlers_options[$selection_group_plugin] = Html::escape($selection_plugins[$selection_group_id][$selection_group_plugin]['base_plugin_label']);
}
}
$form = array(
'#type' => 'container',
'#process' => array(array(get_class($this), 'fieldSettingsAjaxProcess')),
'#element_validate' => array(array(get_class($this), 'fieldSettingsFormValidate')),
);
$form['handler'] = array(
'#type' => 'details',
'#title' => t('Reference type'),
'#open' => TRUE,
'#tree' => TRUE,
'#process' => array(array(get_class($this), 'formProcessMergeParent')),
);
$form['handler']['handler'] = array(
'#type' => 'select',
'#title' => t('Reference method'),
'#options' => $handlers_options,
'#default_value' => $field->getSetting('handler'),
'#required' => TRUE,
'#ajax' => TRUE,
'#limit_validation_errors' => array(),
);
$form['handler']['handler_submit'] = array(
'#type' => 'submit',
'#value' => t('Change handler'),
'#limit_validation_errors' => array(),
'#attributes' => array(
'class' => array('js-hide'),
),
'#submit' => array(array(get_class($this), 'settingsAjaxSubmit')),
);
$form['handler']['handler_settings'] = array(
'#type' => 'container',
'#attributes' => array('class' => array('entity_reference-settings')),
);
$handler = \Drupal::service('plugin.manager.entity_reference_selection')->getSelectionHandler($field);
$form['handler']['handler_settings'] += $handler->buildConfigurationForm(array(), $form_state);
return $form;
}
/**
* Form element validation handler; Invokes selection plugin's validation.
*
* @param array $form
* The form where the settings form is being included in.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state of the (entire) configuration form.
*/
public static function fieldSettingsFormValidate(array $form, FormStateInterface $form_state) {
$field = $form_state->getFormObject()->getEntity();
$handler = \Drupal::service('plugin.manager.entity_reference_selection')->getSelectionHandler($field);
$handler->validateConfigurationForm($form, $form_state);
}
/**
* Determines whether the item holds an unsaved entity.
*
@ -393,4 +507,143 @@ class EntityReferenceItem extends FieldItemBase {
return $changed;
}
/**
* {@inheritdoc}
*/
public function getPossibleValues(AccountInterface $account = NULL) {
return $this->getSettableValues($account);
}
/**
* {@inheritdoc}
*/
public function getPossibleOptions(AccountInterface $account = NULL) {
return $this->getSettableOptions($account);
}
/**
* {@inheritdoc}
*/
public function getSettableValues(AccountInterface $account = NULL) {
// Flatten options first, because "settable options" may contain group
// arrays.
$flatten_options = OptGroup::flattenOptions($this->getSettableOptions($account));
return array_keys($flatten_options);
}
/**
* {@inheritdoc}
*/
public function getSettableOptions(AccountInterface $account = NULL) {
$field_definition = $this->getFieldDefinition();
if (!$options = \Drupal::service('plugin.manager.entity_reference_selection')->getSelectionHandler($field_definition, $this->getEntity())->getReferenceableEntities()) {
return array();
}
// Rebuild the array by changing the bundle key into the bundle label.
$target_type = $field_definition->getSetting('target_type');
$bundles = \Drupal::entityManager()->getBundleInfo($target_type);
$return = array();
foreach ($options as $bundle => $entity_ids) {
// The label does not need sanitizing since it is used as an optgroup
// which is only supported by select elements and auto-escaped.
$bundle_label = (string) $bundles[$bundle]['label'];
$return[$bundle_label] = $entity_ids;
}
return count($return) == 1 ? reset($return) : $return;
}
/**
* Render API callback: Processes the field settings form and allows access to
* the form state.
*
* @see static::fieldSettingsForm()
*/
public static function fieldSettingsAjaxProcess($form, FormStateInterface $form_state) {
static::fieldSettingsAjaxProcessElement($form, $form);
return $form;
}
/**
* Adds entity_reference specific properties to AJAX form elements from the
* field settings form.
*
* @see static::fieldSettingsAjaxProcess()
*/
public static function fieldSettingsAjaxProcessElement(&$element, $main_form) {
if (!empty($element['#ajax'])) {
$element['#ajax'] = array(
'callback' => array(get_called_class(), 'settingsAjax'),
'wrapper' => $main_form['#id'],
'element' => $main_form['#array_parents'],
);
}
foreach (Element::children($element) as $key) {
static::fieldSettingsAjaxProcessElement($element[$key], $main_form);
}
}
/**
* 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()
*/
public static function formProcessMergeParent($element) {
$parents = $element['#parents'];
array_pop($parents);
$element['#parents'] = $parents;
return $element;
}
/**
* Ajax callback for the handler settings form.
*
* @see static::fieldSettingsForm()
*/
public static function settingsAjax($form, FormStateInterface $form_state) {
return NestedArray::getValue($form, $form_state->getTriggeringElement()['#ajax']['element']);
}
/**
* Submit handler for the non-JS case.
*
* @see static::fieldSettingsForm()
*/
public static function settingsAjaxSubmit($form, FormStateInterface $form_state) {
$form_state->setRebuild();
}
/**
* {@inheritdoc}
*/
public static function getPreconfiguredOptions() {
$options = array();
// Add all the commonly referenced entity types as distinct pre-configured
// options.
$entity_types = \Drupal::entityManager()->getDefinitions();
$common_references = array_filter($entity_types, function (EntityTypeInterface $entity_type) {
return $entity_type->isCommonReferenceTarget();
});
/** @var \Drupal\Core\Entity\EntityTypeInterface $entity_type */
foreach ($common_references as $entity_type) {
$options[$entity_type->id()] = [
'label' => $entity_type->getLabel(),
'field_storage_config' => [
'settings' => [
'target_type' => $entity_type->id(),
]
]
];
}
return $options;
}
}

View File

@ -18,6 +18,7 @@ use Drupal\Core\Form\FormStateInterface;
* label = @Translation("Check boxes/radio buttons"),
* field_types = {
* "boolean",
* "entity_reference",
* "list_integer",
* "list_float",
* "list_string",

View File

@ -18,6 +18,7 @@ use Drupal\Core\Form\FormStateInterface;
* id = "options_select",
* label = @Translation("Select list"),
* field_types = {
* "entity_reference",
* "list_integer",
* "list_float",
* "list_string"

View File

@ -6,6 +6,5 @@ version: VERSION
core: 8.x
configure: aggregator.admin_settings
dependencies:
- entity_reference
- file
- options

View File

@ -5,7 +5,6 @@ dependencies:
- core.entity_view_mode.aggregator_item.summary
module:
- aggregator
- entity_reference
id: aggregator_item.aggregator_item.summary
targetEntityType: aggregator_item
bundle: aggregator_item

View File

@ -24,7 +24,7 @@ class AggregatorTitleTest extends KernelTestBase {
*
* @var array
*/
public static $modules = array('file', 'field', 'options', 'aggregator', 'entity_reference');
public static $modules = ['file', 'field', 'options', 'aggregator'];
/**
* The field name that is tested.

View File

@ -5,7 +5,6 @@ dependencies:
- field.field.node.book.body
- node.type.book
module:
- entity_reference
- text
id: node.book.default
targetEntityType: node

View File

@ -23,7 +23,7 @@ class BookUninstallTest extends KernelTestBase {
*
* @var array
*/
public static $modules = array('system', 'user', 'field', 'filter', 'text', 'entity_reference', 'node', 'book');
public static $modules = ['system', 'user', 'field', 'filter', 'text', 'node', 'book'];
/**
* {@inheritdoc}

View File

@ -32,7 +32,7 @@ class ConfigImportRecreateTest extends KernelTestBase {
*
* @var array
*/
public static $modules = array('system', 'field', 'text', 'user', 'node', 'entity_reference');
public static $modules = ['system', 'field', 'text', 'user', 'node'];
protected function setUp() {
parent::setUp();

View File

@ -34,7 +34,7 @@ class ConfigImportRenameValidationTest extends KernelTestBase {
*
* @var array
*/
public static $modules = array('system', 'user', 'node', 'field', 'text', 'config_test', 'entity_reference');
public static $modules = ['system', 'user', 'node', 'field', 'text', 'config_test'];
/**
* {@inheritdoc}

View File

@ -589,7 +589,7 @@ class ConfigImporterTest extends KernelTestBase {
$error_log = $this->configImporter->getErrors();
$expected = [
'Unable to install the <em class="placeholder">unknown_module</em> module since it does not exist.',
'Unable to install the <em class="placeholder">Book</em> module since it requires the <em class="placeholder">Node, Text, Field, Filter, User, Entity Reference</em> modules.',
'Unable to install the <em class="placeholder">Book</em> module since it requires the <em class="placeholder">Node, Text, Field, Filter, User</em> modules.',
'Unable to install the <em class="placeholder">unknown_theme</em> theme since it does not exist.',
'Unable to install the <em class="placeholder">Bartik</em> theme since it requires the <em class="placeholder">Classy</em> theme.',
'Configuration <em class="placeholder">config_test.dynamic.dotted.config</em> depends on the <em class="placeholder">unknown</em> configuration that will not exist after import.',

View File

@ -1,20 +0,0 @@
# Schema for the views plugins of the Entity Reference module.
views.display.entity_reference:
type: views_display
label: 'Entity Reference'
views.row.entity_reference:
type: views.row.fields
label: 'Entity Reference inline fields'
views.style.entity_reference:
type: views_style
label: 'Entity Reference list'
mapping:
search_fields:
type: sequence
label: 'Search fields'
sequence:
type: string
label: 'Search field'

View File

@ -1,8 +1,7 @@
name: 'Entity Reference'
type: module
description: 'Provides a field that can reference other entities.'
description: 'Deprecated. All the functionality has been moved to Core.'
package: Field types
version: VERSION
core: 8.x
dependencies:
- field
hidden: true

View File

@ -2,205 +2,6 @@
/**
* @file
* Provides a field that can reference other entities.
* Deprecated. All its functionality has been moved to Core. This empty module
* will be removed in Drupal 9.0.x.
*/
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Database\Query\AlterableInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\field\Entity\FieldConfig;
/**
* Implements hook_help().
*/
function entity_reference_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
case 'help.page.entity_reference':
$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 the <a href=":er_do">online documentation for the Entity Reference module</a> and the <a href=":field_help">Field module help page</a>.', array(':field_help' => \Drupal::url('help.page', array('name' => 'field')), ':er_do' => 'https://www.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::moduleHandler()->moduleExists('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 type of item 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. Certain entity types may provide additional display options. You can configure how the entity reference is displayed on the <em>Manage display</em> page for the entity.') . '</dd>';
$output .= '<dt>' . t('Configuring form displays') . '</dt>';
$output .= '<dd>' . t('Reference fields have several widgets available on the <em>Manage form display</em> page:');
$output .= '<ul>';
$output .= '<li>' . t('The <em>Check boxes/radio buttons</em> widget displays the existing entities for the entity type as check boxes or radio buttons based on the <em>Allowed number of values</em> set for the field.') . '</li>';
$output .= '<li>' . t('The <em>Select list</em> widget displays the existing entities in a drop-down list or scrolling list box based on the <em>Allowed number of values</em> setting for the field.') . '</li>';
$output .= '<li>' . t('The <em>Autocomplete</em> widget displays text fields in which users can type entity labels based on the <em>Allowed number of values</em>. The widget can be configured to display all entities that contain the typed characters or restricted to those starting with those characters.') . '</li>';
$output .= '<li>' . t('The <em>Autocomplete (Tags style)</em> widget displays a multi-text field in which users can type in a comma-separated list of entity labels.') . '</li>';
$output .= '</ul>';
$output .= '</dl>';
return $output;
}
}
/**
* Implements hook_field_info_alter().
*/
function entity_reference_field_info_alter(&$info) {
// Make the entity reference field configurable.
$info['entity_reference']['no_ui'] = FALSE;
$info['entity_reference']['class'] = '\Drupal\entity_reference\ConfigurableEntityReferenceItem';
$info['entity_reference']['list_class'] = '\Drupal\Core\Field\EntityReferenceFieldItemList';
$info['entity_reference']['default_widget'] = 'entity_reference_autocomplete';
$info['entity_reference']['default_formatter'] = 'entity_reference_label';
$info['entity_reference']['provider'] = 'entity_reference';
}
/**
* 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';
}
}
/**
* Implements hook_form_FORM_ID_alter() for 'field_ui_field_storage_add_form'.
*/
function entity_reference_form_field_ui_field_storage_add_form_alter(array &$form) {
$optgroup = (string) t('Reference');
// Move the "Entity reference" option to the end of the list and rename it to
// "Other".
unset($form['add']['new_storage_type']['#options'][$optgroup]['entity_reference']);
$form['add']['new_storage_type']['#options'][$optgroup]['entity_reference'] = t('Other…');
}
/**
* Render API callback: Processes the field settings form and allows access to
* the form state.
*
* @see entity_reference_field_field_settings_form()
*/
function _entity_reference_field_field_settings_ajax_process($form, FormStateInterface $form_state) {
_entity_reference_field_field_settings_ajax_process_element($form, $form);
return $form;
}
/**
* Adds entity_reference specific properties to AJAX form elements from the
* field settings form.
*
* @see _entity_reference_field_field_settings_ajax_process()
*/
function _entity_reference_field_field_settings_ajax_process_element(&$element, $main_form) {
if (!empty($element['#ajax'])) {
$element['#ajax'] = array(
'callback' => 'entity_reference_settings_ajax',
'wrapper' => $main_form['#id'],
'element' => $main_form['#array_parents'],
);
}
foreach (Element::children($element) as $key) {
_entity_reference_field_field_settings_ajax_process_element($element[$key], $main_form);
}
}
/**
* 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.
*/
function _entity_reference_element_validate_filter(&$element, FormStateInterface $form_state) {
$element['#value'] = array_filter($element['#value']);
$form_state->setValueForElement($element, $element['#value']);
}
/**
* Ajax callback for the handler settings form.
*
* @see entity_reference_field_field_settings_form()
*/
function entity_reference_settings_ajax($form, FormStateInterface $form_state) {
return NestedArray::getValue($form, $form_state->getTriggeringElement()['#ajax']['element']);
}
/**
* Submit handler for the non-JS case.
*
* @see entity_reference_field_field_settings_form()
*/
function entity_reference_settings_ajax_submit($form, FormStateInterface $form_state) {
$form_state->setRebuild();
}
/**
* Implements hook_query_TAG_alter().
*/
function entity_reference_query_entity_reference_alter(AlterableInterface $query) {
$handler = $query->getMetadata('entity_reference_selection_handler');
$handler->entityQueryAlter($query);
}
/**
* Implements hook_entity_bundle_delete().
*
* We are duplicating the work done by
* \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem::onDependencyRemoval()
* because we need to take into account bundles that are not provided by a
* config entity type so they are not part of the config dependencies.
*/
function entity_reference_entity_bundle_delete($entity_type_id, $bundle) {
// Gather a list of all entity reference fields.
$map = \Drupal::entityManager()->getFieldMapByFieldType('entity_reference');
$ids = [];
foreach ($map as $type => $info) {
foreach ($info as $name => $data) {
foreach ($data['bundles'] as $bundle_name) {
$ids[] = "$type.$bundle_name.$name";
}
}
}
// Update the 'target_bundles' handler setting if needed.
foreach (FieldConfig::loadMultiple($ids) as $field_config) {
if ($field_config->getSetting('target_type') == $entity_type_id) {
$handler_settings = $field_config->getSetting('handler_settings');
if (isset($handler_settings['target_bundles'][$bundle])) {
unset($handler_settings['target_bundles'][$bundle]);
$field_config->setSetting('handler_settings', $handler_settings);
$field_config->save();
// In case we deleted the only target bundle allowed by the field we
// have to log a warning message because the field will not function
// correctly anymore.
if ($handler_settings['target_bundles'] === []) {
\Drupal::logger('entity_reference')->critical('The %target_bundle bundle (entity type: %target_entity_type) was deleted. As a result, the %field_name entity reference field (entity_type: %entity_type, bundle: %bundle) no longer has any valid bundle it can reference. The field is not working correctly anymore and has to be adjusted.', [
'%target_bundle' => $bundle,
'%target_entity_type' => $entity_type_id,
'%field_name' => $field_config->getName(),
'%entity_type' => $field_config->getTargetEntityTypeId(),
'%bundle' => $field_config->getTargetBundle()
]);
}
}
}
}
}

View File

@ -1,73 +0,0 @@
<?php
/**
* @file
* Provides views data for the entity_reference module.
*/
use Drupal\field\FieldStorageConfigInterface;
/**
* Implements hook_field_views_data().
*/
function entity_reference_field_views_data(FieldStorageConfigInterface $field_storage) {
$data = views_field_default_views_data($field_storage);
$entity_manager = \Drupal::entityManager();
foreach ($data as $table_name => $table_data) {
// Add a relationship to the target entity type.
$target_entity_type_id = $field_storage->getSetting('target_type');
$target_entity_type = $entity_manager->getDefinition($target_entity_type_id);
$entity_type_id = $field_storage->getTargetEntityTypeId();
$entity_type = $entity_manager->getDefinition($entity_type_id);
$target_base_table = $target_entity_type->getDataTable() ?: $target_entity_type->getBaseTable();
$field_name = $field_storage->getName();
// Provide a relationship for the entity type with the entity reference
// field.
$args = array(
'@label' => $target_entity_type->getLabel(),
'@field_name' => $field_name,
);
$data[$table_name][$field_name]['relationship'] = array(
'title' => t('@label referenced from @field_name', $args),
'label' => t('@field_name: @label', $args),
'group' => $entity_type->getLabel(),
'help' => t('Appears in: @bundles.', array('@bundles' => implode(', ', $field_storage->getBundles()))),
'id' => 'standard',
'base' => $target_base_table,
'entity type' => $target_entity_type_id,
'base field' => $target_entity_type->getKey('id'),
'relationship field' => $field_name . '_target_id',
);
// Provide a reverse relationship for the entity type that is referenced by
// the field.
$args['@entity'] = $entity_type->getLabel();
$args['@label'] = $target_entity_type->getLowercaseLabel();
$pseudo_field_name = 'reverse__' . $entity_type_id . '__' . $field_name;
/** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */
$table_mapping = $entity_manager->getStorage($entity_type_id)->getTableMapping();
$data[$target_base_table][$pseudo_field_name]['relationship'] = array(
'title' => t('@entity using @field_name', $args),
'label' => t('@field_name', array('@field_name' => $field_name)),
'group' => $target_entity_type->getLabel(),
'help' => t('Relate each @entity with a @field_name set to the @label.', $args),
'id' => 'entity_reverse',
'base' => $entity_type->getDataTable() ?: $entity_type->getBaseTable(),
'entity_type' => $entity_type_id,
'base field' => $entity_type->getKey('id'),
'field_name' => $field_name,
'field table' => $table_mapping->getDedicatedDataTableName($field_storage),
'field field' => $field_name . '_target_id',
'join_extra' => array(
array(
'field' => 'deleted',
'value' => 0,
'numeric' => TRUE,
),
),
);
}
return $data;
}

View File

@ -7,218 +7,14 @@
namespace Drupal\entity_reference;
use Drupal\Component\Utility\Html;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
use Drupal\Core\Field\PreconfiguredFieldUiOptionsInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Form\OptGroup;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\TypedData\OptionsProviderInterface;
use Drupal\Core\Validation\Plugin\Validation\Constraint\AllowedValuesConstraint;
/**
* Alternative plugin implementation of the 'entity_reference' field type.
* Deprecated. Alternative implementation of the 'entity_reference' field type.
*
* Replaces the Core 'entity_reference' entity field type implementation, this
* supports configurable fields, auto-creation of referenced entities and more.
* @deprecated in Drupal 8.0.x and will be removed in Drupal 9.0.x. Use
* \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem instead.
*
* Required settings are:
* - target_type: The entity type to reference.
*
* @see entity_reference_field_info_alter().
* @see \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem
*/
class ConfigurableEntityReferenceItem extends EntityReferenceItem implements OptionsProviderInterface, PreconfiguredFieldUiOptionsInterface {
/**
* {@inheritdoc}
*/
public function getPossibleValues(AccountInterface $account = NULL) {
return $this->getSettableValues($account);
}
/**
* {@inheritdoc}
*/
public function getPossibleOptions(AccountInterface $account = NULL) {
return $this->getSettableOptions($account);
}
/**
* {@inheritdoc}
*/
public function getSettableValues(AccountInterface $account = NULL) {
// Flatten options first, because "settable options" may contain group
// arrays.
$flatten_options = OptGroup::flattenOptions($this->getSettableOptions($account));
return array_keys($flatten_options);
}
/**
* {@inheritdoc}
*/
public function getSettableOptions(AccountInterface $account = NULL) {
$field_definition = $this->getFieldDefinition();
if (!$options = \Drupal::service('plugin.manager.entity_reference_selection')->getSelectionHandler($field_definition, $this->getEntity())->getReferenceableEntities()) {
return array();
}
// Rebuild the array by changing the bundle key into the bundle label.
$target_type = $field_definition->getSetting('target_type');
$bundles = \Drupal::entityManager()->getBundleInfo($target_type);
$return = array();
foreach ($options as $bundle => $entity_ids) {
// The label does not need sanitizing since it is used as an optgroup
// which is only supported by select elements and auto-escaped.
$bundle_label = $bundles[$bundle]['label'];
$return[(string) $bundle_label] = $entity_ids;
}
return count($return) == 1 ? reset($return) : $return;
}
/**
* {@inheritdoc}
*/
public function getConstraints() {
$constraints = parent::getConstraints();
// Remove the 'AllowedValuesConstraint' validation constraint because entity
// reference fields already use the 'ValidReference' constraint.
foreach ($constraints as $key => $constraint) {
if ($constraint instanceof AllowedValuesConstraint) {
unset($constraints[$key]);
}
}
return $constraints;
}
/**
* {@inheritdoc}
*/
public function storageSettingsForm(array &$form, FormStateInterface $form_state, $has_data) {
$element['target_type'] = array(
'#type' => 'select',
'#title' => t('Type of item to reference'),
'#options' => \Drupal::entityManager()->getEntityTypeLabels(TRUE),
'#default_value' => $this->getSetting('target_type'),
'#required' => TRUE,
'#disabled' => $has_data,
'#size' => 1,
);
return $element;
}
/**
* {@inheritdoc}
*/
public function fieldSettingsForm(array $form, FormStateInterface $form_state) {
$field = $form_state->getFormObject()->getEntity();
// Get all selection plugins for this entity type.
$selection_plugins = \Drupal::service('plugin.manager.entity_reference_selection')->getSelectionGroups($this->getSetting('target_type'));
$handlers_options = array();
foreach (array_keys($selection_plugins) as $selection_group_id) {
// We only display base plugins (e.g., 'default', 'views', etc.) and not
// entity type specific plugins (e.g., 'default:node', 'default:user',
// etc.).
if (array_key_exists($selection_group_id, $selection_plugins[$selection_group_id])) {
$handlers_options[$selection_group_id] = Html::escape($selection_plugins[$selection_group_id][$selection_group_id]['label']);
}
elseif (array_key_exists($selection_group_id . ':' . $this->getSetting('target_type'), $selection_plugins[$selection_group_id])) {
$selection_group_plugin = $selection_group_id . ':' . $this->getSetting('target_type');
$handlers_options[$selection_group_plugin] = Html::escape($selection_plugins[$selection_group_id][$selection_group_plugin]['base_plugin_label']);
}
}
$form = array(
'#type' => 'container',
'#process' => array(
'_entity_reference_field_field_settings_ajax_process',
),
'#element_validate' => array(array(get_class($this), 'fieldSettingsFormValidate')),
);
$form['handler'] = array(
'#type' => 'details',
'#title' => t('Reference type'),
'#open' => TRUE,
'#tree' => TRUE,
'#process' => array('_entity_reference_form_process_merge_parent'),
);
$form['handler']['handler'] = array(
'#type' => 'select',
'#title' => t('Reference method'),
'#options' => $handlers_options,
'#default_value' => $field->getSetting('handler'),
'#required' => TRUE,
'#ajax' => TRUE,
'#limit_validation_errors' => array(),
);
$form['handler']['handler_submit'] = array(
'#type' => 'submit',
'#value' => t('Change handler'),
'#limit_validation_errors' => array(),
'#attributes' => array(
'class' => array('js-hide'),
),
'#submit' => array('entity_reference_settings_ajax_submit'),
);
$form['handler']['handler_settings'] = array(
'#type' => 'container',
'#attributes' => array('class' => array('entity_reference-settings')),
);
$handler = \Drupal::service('plugin.manager.entity_reference_selection')->getSelectionHandler($field);
$form['handler']['handler_settings'] += $handler->buildConfigurationForm(array(), $form_state);
return $form;
}
/**
* Form element validation handler; Invokes selection plugin's validation.
*
* @param array $form
* The form where the settings form is being included in.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state of the (entire) configuration form.
*/
public static function fieldSettingsFormValidate(array $form, FormStateInterface $form_state) {
$field = $form_state->getFormObject()->getEntity();
$handler = \Drupal::service('plugin.manager.entity_reference_selection')->getSelectionHandler($field);
$handler->validateConfigurationForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public static function getPreconfiguredOptions() {
$options = array();
// Add all the commonly referenced entity types as distinct pre-configured
// options.
$entity_types = \Drupal::entityManager()->getDefinitions();
$common_references = array_filter($entity_types, function (EntityTypeInterface $entity_type) {
return $entity_type->isCommonReferenceTarget();
});
/** @var \Drupal\Core\Entity\EntityTypeInterface $entity_type */
foreach ($common_references as $entity_type) {
$options[$entity_type->id()] = [
'label' => $entity_type->getLabel(),
'field_storage_config' => [
'settings' => [
'target_type' => $entity_type->id(),
]
]
];
}
return $options;
}
}
class ConfigurableEntityReferenceItem extends EntityReferenceItem { }

View File

@ -7,176 +7,14 @@
namespace Drupal\entity_reference\Plugin\views\display;
use Drupal\views\Plugin\views\display\DisplayPluginBase;
use Drupal\views\Plugin\views\display\EntityReference as ViewsEntityReference;
/**
* The plugin that handles an EntityReference display.
* Deprecated. The plugin that handles an EntityReference display.
*
* "entity_reference_display" is a custom property, used with
* \Drupal\views\Views::getApplicableViews() to retrieve all views with a
* 'Entity Reference' display.
* @deprecated in Drupal 8.0.x and will be removed in Drupal 9.0.x. Use
* \Drupal\views\Plugin\views\display\EntityReference instead.
*
* @ingroup views_display_plugins
*
* @ViewsDisplay(
* id = "entity_reference",
* title = @Translation("Entity Reference"),
* admin = @Translation("Entity Reference Source"),
* help = @Translation("Selects referenceable entities for an entity reference field."),
* theme = "views_view",
* register_theme = FALSE,
* uses_menu_links = FALSE,
* entity_reference_display = TRUE
* )
* @see \Drupal\views\Plugin\views\display\EntityReference
*/
class EntityReference extends DisplayPluginBase {
/**
* Overrides \Drupal\views\Plugin\views\display\DisplayPluginBase::$useAJAX.
*/
protected $usesAJAX = FALSE;
/**
* Overrides \Drupal\views\Plugin\views\display\DisplayPluginBase::$usesPager.
*/
protected $usesPager = FALSE;
/**
* Overrides \Drupal\views\Plugin\views\display\DisplayPluginBase::$usesAttachments.
*/
protected $usesAttachments = FALSE;
/**
* Overrides \Drupal\views\Plugin\views\display\DisplayPluginBase::defineOptions().
*/
protected function defineOptions() {
$options = parent::defineOptions();
// Force the style plugin to 'entity_reference_style' and the row plugin to
// 'fields'.
$options['style']['contains']['type'] = array('default' => 'entity_reference');
$options['defaults']['default']['style'] = FALSE;
$options['row']['contains']['type'] = array('default' => 'entity_reference');
$options['defaults']['default']['row'] = FALSE;
// Make sure the query is not cached.
$options['defaults']['default']['cache'] = FALSE;
// Set the display title to an empty string (not used in this display type).
$options['title']['default'] = '';
$options['defaults']['default']['title'] = FALSE;
return $options;
}
/**
* Overrides \Drupal\views\Plugin\views\display\DisplayPluginBase::optionsSummary().
*
* Disable 'cache' and 'title' so it won't be changed.
*/
public function optionsSummary(&$categories, &$options) {
parent::optionsSummary($categories, $options);
unset($options['query']);
unset($options['title']);
}
/**
* Overrides \Drupal\views\Plugin\views\display\DisplayPluginBase::getType().
*/
public function getType() {
return 'entity_reference';
}
/**
* Overrides \Drupal\views\Plugin\views\display\DisplayPluginBase::execute().
*/
public function execute() {
return $this->view->render($this->display['id']);
}
/**
* Overrides \Drupal\views\Plugin\views\display\DisplayPluginBase::render().
*/
public function render() {
if (!empty($this->view->result) && $this->view->style_plugin->evenEmpty()) {
return $this->view->style_plugin->render($this->view->result);
}
return '';
}
/**
* Overrides \Drupal\views\Plugin\views\display\DisplayPluginBase::usesExposed().
*/
public function usesExposed() {
return FALSE;
}
/**
* Overrides \Drupal\views\Plugin\views\display\DisplayPluginBase::query().
*/
public function query() {
if (!empty($this->view->live_preview)) {
return;
}
// Make sure the id field is included in the results.
$id_field = $this->view->storage->get('base_field');
$this->id_field_alias = $this->view->query->addField($this->view->storage->get('base_table'), $id_field);
$options = $this->getOption('entity_reference_options');
// Restrict the autocomplete options based on what's been typed already.
if (isset($options['match'])) {
$style_options = $this->getOption('style');
$value = db_like($options['match']) . '%';
if ($options['match_operator'] != 'STARTS_WITH') {
$value = '%' . $value;
}
// Multiple search fields are OR'd together.
$conditions = db_or();
// Build the condition using the selected search fields.
foreach ($style_options['options']['search_fields'] as $field_id) {
if (!empty($field_id)) {
// Get the table and field names for the checked field.
$field_alias = $this->view->query->addField($this->view->field[$field_id]->table, $field_id);
$field = $this->view->query->fields[$field_alias];
// Add an OR condition for the field.
$conditions->condition($field['table'] . '.' . $field['field'], $value, 'LIKE');
}
}
$this->view->query->addWhere(0, $conditions);
}
// Add an IN condition for validation.
if (!empty($options['ids'])) {
$this->view->query->addWhere(0, $id_field, $options['ids']);
}
$this->view->setItemsPerPage($options['limit']);
}
/**
* Overrides \Drupal\views\Plugin\views\display\DisplayPluginBase::validate().
*/
public function validate() {
$errors = parent::validate();
// Verify that search fields are set up.
$style = $this->getOption('style');
if (!isset($style['options']['search_fields'])) {
$errors[] = $this->t('Display "@display" needs a selected search fields to work properly. See the settings for the Entity Reference list format.', array('@display' => $this->display['display_title']));
}
else {
// Verify that the search fields used actually exist.
$fields = array_keys($this->handlers['field']);
foreach ($style['options']['search_fields'] as $field_alias => $enabled) {
if ($enabled && !in_array($field_alias, $fields)) {
$errors[] = $this->t('Display "@display" uses field %field as search field, but the field is no longer present. See the settings for the Entity Reference list format.', array('@display' => $this->display['display_title'], '%field' => $field_alias));
}
}
}
return $errors;
}
}
class EntityReference extends ViewsEntityReference { }

View File

@ -7,56 +7,14 @@
namespace Drupal\entity_reference\Plugin\views\row;
use Drupal\Core\Form\FormStateInterface;
use Drupal\views\Plugin\views\row\Fields;
use Drupal\views\Plugin\views\row\EntityReference as ViewsEntityReference;
/**
* EntityReference row plugin.
*
* @ingroup views_row_plugins
* @deprecated in Drupal 8.0.x and will be removed in Drupal 9.0.x. Use
* \Drupal\views\Plugin\views\row\EntityReference instead.
*
* @ViewsRow(
* id = "entity_reference",
* title = @Translation("Entity Reference inline fields"),
* help = @Translation("Displays the fields with an optional template."),
* theme = "views_view_fields",
* register_theme = FALSE,
* display_types = {"entity_reference"}
* )
* @see \Drupal\views\Plugin\views\row\EntityReference
*/
class EntityReference extends Fields {
/**
* Overrides \Drupal\views\Plugin\views\row\Fields::defineOptions().
*/
protected function defineOptions() {
$options = parent::defineOptions();
$options['separator'] = array('default' => '-');
return $options;
}
/**
* Overrides \Drupal\views\Plugin\views\row\Fields::buildOptionsForm().
*/
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
parent::buildOptionsForm($form, $form_state);
// Expand the description of the 'Inline field' checkboxes.
$form['inline']['#description'] .= '<br />' . $this->t("<strong>Note:</strong> In 'Entity Reference' displays, all fields will be displayed inline unless an explicit selection of inline fields is made here." );
}
/**
* {@inheritdoc}
*/
public function preRender($row) {
// Force all fields to be inline by default.
if (empty($this->options['inline'])) {
$fields = $this->view->getHandlers('field', $this->displayHandler->display['id']);
$names = array_keys($fields);
$this->options['inline'] = array_combine($names, $names);
}
return parent::preRender($row);
}
}
class EntityReference extends ViewsEntityReference { }

View File

@ -7,103 +7,14 @@
namespace Drupal\entity_reference\Plugin\views\style;
use Drupal\Component\Utility\Xss;
use Drupal\Core\Form\FormStateInterface;
use Drupal\views\Plugin\views\style\StylePluginBase;
use Drupal\views\Plugin\views\style\EntityReference as ViewsEntityReference;
/**
* EntityReference style plugin.
* Deprecated. EntityReference style plugin.
*
* @ingroup views_style_plugins
* @deprecated in Drupal 8.0.x and will be removed in Drupal 9.0.x. Use
* \Drupal\views\Plugin\views\style\EntityReference instead.
*
* @ViewsStyle(
* id = "entity_reference",
* title = @Translation("Entity Reference list"),
* help = @Translation("Returns results as a PHP array of labels and rendered rows."),
* theme = "views_view_unformatted",
* register_theme = FALSE,
* display_types = {"entity_reference"}
* )
* @see \Drupal\views\Plugin\views\style\EntityReference
*/
class EntityReference extends StylePluginBase {
/**
* Overrides \Drupal\views\Plugin\views\style\StylePluginBase::usesRowPlugin.
*/
protected $usesRowPlugin = TRUE;
/**
* Overrides \Drupal\views\Plugin\views\style\StylePluginBase::usesFields.
*/
protected $usesFields = TRUE;
/**
* Overrides \Drupal\views\Plugin\views\style\StylePluginBase::usesGrouping.
*/
protected $usesGrouping = FALSE;
/**
* Overrides \Drupal\views\Plugin\views\style\StylePluginBase\StylePluginBase::defineOptions().
*/
protected function defineOptions() {
$options = parent::defineOptions();
$options['search_fields'] = array('default' => array());
return $options;
}
/**
* Overrides \Drupal\views\Plugin\views\style\StylePluginBase\StylePluginBase::buildOptionsForm().
*/
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
parent::buildOptionsForm($form, $form_state);
$options = $this->displayHandler->getFieldLabels(TRUE);
$form['search_fields'] = array(
'#type' => 'checkboxes',
'#title' => $this->t('Search fields'),
'#options' => $options,
'#required' => TRUE,
'#default_value' => $this->options['search_fields'],
'#description' => $this->t('Select the field(s) that will be searched when using the autocomplete widget.'),
'#weight' => -3,
);
}
/**
* Overrides \Drupal\views\Plugin\views\style\StylePluginBase\StylePluginBase::render().
*/
public function render() {
if (!empty($this->view->live_preview)) {
return parent::render();
}
// Group the rows according to the grouping field, if specified.
$sets = $this->renderGrouping($this->view->result, $this->options['grouping']);
// Grab the alias of the 'id' field added by
// entity_reference_plugin_display.
$id_field_alias = $this->view->storage->get('base_field');
// @todo We don't display grouping info for now. Could be useful for select
// widget, though.
$results = array();
foreach ($sets as $records) {
foreach ($records as $values) {
$results[$values->{$id_field_alias}] = $this->view->rowPlugin->render($values);
// Sanitize HTML, remove line breaks and extra whitespace.
$results[$values->{$id_field_alias}]['#post_render'][] = function ($html, array $elements) {
return Xss::filterAdmin(preg_replace('/\s\s+/', ' ', str_replace("\n", '', $html)));
};
}
}
return $results;
}
/**
* {@inheritdoc}
*/
public function evenEmpty() {
return TRUE;
}
}
class EntityReference extends ViewsEntityReference { }

View File

@ -5,6 +5,8 @@
* Install, update and uninstall functions for the field module.
*/
use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
/**
* Removes the stale 'target_bundle' storage setting on entity_reference fields.
*/
@ -12,7 +14,6 @@ function field_update_8001() {
$config = \Drupal::configFactory();
/** @var \Drupal\Core\Field\FieldTypePluginManager $field_type_manager */
$field_type_manager = \Drupal::service('plugin.manager.field.field_type');
$item_class = 'Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem';
// Iterate on all fields storage.
foreach ($config->listAll('field.storage.') as $field_id) {
@ -20,9 +21,50 @@ function field_update_8001() {
$class = $field_type_manager->getPluginClass($field_storage->get('type'));
// Deal only with entity reference fields and descendants.
if ($class == $item_class || is_subclass_of($class, $item_class)) {
if ($class == EntityReferenceItem::class || is_subclass_of($class, EntityReferenceItem::class)) {
// Remove 'target_bundle' from settings.
$field_storage->clear('settings.target_bundle')->save(TRUE);
}
}
}
/**
* The 'entity_reference' field type is now provided by core.
*/
function field_update_8002() {
$config_factory = \Drupal::configFactory();
// Iterate on all configuration entities.
foreach ($config_factory->listAll() as $id) {
$changed = FALSE;
$config = $config_factory->getEditable($id);
// Update field storage configurations.
if (strpos($id, 'field.storage.') === 0) {
// Deal only with entity reference fields.
if ($config->get('type') == 'entity_reference') {
// Fix the type provider.
$config->set('module', 'core');
$changed = TRUE;
}
}
// Remove entity_reference module dependency from any configuration entity.
if ($dependencies = $config->get('dependencies.module')) {
if (($delta = array_search('entity_reference', $dependencies)) !== FALSE) {
unset($dependencies[$delta]);
if ($dependencies) {
$config->set('dependencies.module', array_values($dependencies));
}
else {
$config->clear('dependencies.module');
}
$changed = TRUE;
}
}
if ($changed) {
$config->save(TRUE);
}
}
}

View File

@ -130,6 +130,25 @@ function field_help($route_name, RouteMatchInterface $route_match) {
$output .= '<dt>' . t('Provided by Drupal core') . '</dt>';
$output .= '<dd>' . t('As mentioned previously, some field types, widgets, and formatters are provided by Drupal core. Here are some notes on how to use some of these:');
$output .= '<ul>';
$output .= '<li><p>' . t('<strong>Entity Reference</strong> fields allow 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>.', array(':er_do' => 'https://drupal.org/documentation/modules/entityreference')) . '</p>';
$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 .= '<dt>' . t('Configuring form displays') . '</dt>';
$output .= '<dd>' . t('Reference fields have several widgets available on the <em>Manage form display</em> page:');
$output .= '<ul>';
$output .= '<li>' . t('The <em>Check boxes/radio buttons</em> widget displays the existing entities for the entity type as check boxes or radio buttons based on the <em>Allowed number of values</em> set for the field.') . '</li>';
$output .= '<li>' . t('The <em>Select list</em> widget displays the existing entities in a drop-down list or scrolling list box based on the <em>Allowed number of values</em> setting for the field.') . '</li>';
$output .= '<li>' . t('The <em>Autocomplete</em> widget displays text fields in which users can type entity labels based on the <em>Allowed number of values</em>. The widget can be configured to display all entities that contain the typed characters or restricted to those starting with those characters.') . '</li>';
$output .= '<li>' . t('The <em>Autocomplete (Tags style)</em> widget displays a multi-text field in which users can type in a comma-separated list of entity labels.') . '</li>';
$output .= '</ul></dd>';
$output .= '</dl></li>';
$output .= '<li>' . t('<strong>Number fields</strong>: When you add a number field you can choose from three types: <em>decimal</em>, <em>float</em>, and <em>integer</em>. The <em>decimal</em> number field type allows users to enter exact decimal values, with fixed numbers of decimal places. The <em>float</em> number field type allows users to enter approximate decimal values. The <em>integer</em> number field type allows users to enter whole numbers, such as years (for example, 2012) or values (for example, 1, 2, 5, 305). It does not allow decimals.') . '</li>';
$output .= '</ul></dd>';
$output .= '</dl>';
@ -190,20 +209,61 @@ function field_entity_bundle_field_info(EntityTypeInterface $entity_type, $bundl
/**
* Implements hook_entity_bundle_delete().
*
* This deletes the data for the field as well as the field themselves. This
* function actually just marks the data and fields as deleted, leaving the
* garbage collection for a separate process, because it is not always
* possible to delete this much data in a single page request (particularly
* since for some field types, the deletion is more than just a simple DELETE
* query).
*/
function field_entity_bundle_delete($entity_type, $bundle) {
function field_entity_bundle_delete($entity_type_id, $bundle) {
$storage = \Drupal::entityManager()->getStorage('field_config');
// Get the fields on the bundle.
$fields = entity_load_multiple_by_properties('field_config', array('entity_type' => $entity_type, 'bundle' => $bundle));
$fields = $storage->loadByProperties(['entity_type' => $entity_type_id, 'bundle' => $bundle]);
// This deletes the data for the field as well as the field themselves. This
// function actually just marks the data and fields as deleted, leaving the
// garbage collection for a separate process, because it is not always
// possible to delete this much data in a single page request (particularly
// since for some field types, the deletion is more than just a simple DELETE
// query).
foreach ($fields as $field) {
$field->delete();
}
// We are duplicating the work done by
// \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem::onDependencyRemoval()
// because we need to take into account bundles that are not provided by a
// config entity type so they are not part of the config dependencies.
// Gather a list of all entity reference fields.
$map = \Drupal::entityManager()->getFieldMapByFieldType('entity_reference');
$ids = [];
foreach ($map as $type => $info) {
foreach ($info as $name => $data) {
foreach ($data['bundles'] as $bundle_name) {
$ids[] = "$type.$bundle_name.$name";
}
}
}
// Update the 'target_bundles' handler setting if needed.
foreach (FieldConfig::loadMultiple($ids) as $field_config) {
if ($field_config->getSetting('target_type') == $entity_type_id) {
$handler_settings = $field_config->getSetting('handler_settings');
if (isset($handler_settings['target_bundles'][$bundle])) {
unset($handler_settings['target_bundles'][$bundle]);
$field_config->setSetting('handler_settings', $handler_settings);
$field_config->save();
// In case we deleted the only target bundle allowed by the field we
// have to log a warning message because the field will not function
// correctly anymore.
if ($handler_settings['target_bundles'] === []) {
\Drupal::logger('entity_reference')->critical('The %target_bundle bundle (entity type: %target_entity_type) was deleted. As a result, the %field_name entity reference field (entity_type: %entity_type, bundle: %bundle) no longer has any valid bundle it can reference. The field is not working correctly anymore and has to be adjusted.', [
'%target_bundle' => $bundle,
'%target_entity_type' => $entity_type_id,
'%field_name' => $field_config->getName(),
'%entity_type' => $field_config->getTargetEntityTypeId(),
'%bundle' => $field_config->getTargetBundle()
]);
}
}
}
}
}
/**

View File

@ -2,10 +2,10 @@
/**
* @file
* Contains \Drupal\entity_reference\Tests\EntityReferenceAdminTest.
* Contains \Drupal\field\Tests\EntityReference\EntityReferenceAdminTest.
*/
namespace Drupal\entity_reference\Tests;
namespace Drupal\field\Tests\EntityReference;
use Drupal\Core\Entity\Entity;
use Drupal\field_ui\Tests\FieldUiTestTrait;
@ -31,7 +31,7 @@ class EntityReferenceAdminTest extends WebTestBase {
*
* @var array
*/
public static $modules = array('node', 'field_ui', 'entity_reference', 'path', 'taxonomy', 'block', 'views', 'views_ui', 'entity_test');
public static $modules = ['node', 'field_ui', 'path', 'taxonomy', 'block', 'views_ui'];
/**
* The name of the content type created for testing purposes.

View File

@ -2,10 +2,10 @@
/**
* @file
* Contains \Drupal\entity_reference\Tests\EntityReferenceAutoCreateTest.
* Contains \Drupal\field\Tests\EntityReference\EntityReferenceAutoCreateTest.
*/
namespace Drupal\entity_reference\Tests;
namespace Drupal\field\Tests\EntityReference;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\simpletest\WebTestBase;
@ -18,7 +18,7 @@ use Drupal\node\Entity\Node;
*/
class EntityReferenceAutoCreateTest extends WebTestBase {
public static $modules = array('entity_reference', 'node');
public static $modules = ['node'];
/**
* The name of a content type that will reference $referencedType.

View File

@ -2,10 +2,10 @@
/**
* @file
* Contains \Drupal\entity_reference\Tests\EntityReferenceFieldDefaultValueTest.
* Contains \Drupal\field\Tests\EntityReference\EntityReferenceFieldDefaultValueTest.
*/
namespace Drupal\entity_reference\Tests;
namespace Drupal\field\Tests\EntityReference;
use Drupal\Component\Utility\Unicode;
use Drupal\config\Tests\SchemaCheckTestTrait;
@ -18,6 +18,7 @@ use Drupal\simpletest\WebTestBase;
* @group entity_reference
*/
class EntityReferenceFieldDefaultValueTest extends WebTestBase {
use SchemaCheckTestTrait;
/**
@ -25,7 +26,7 @@ class EntityReferenceFieldDefaultValueTest extends WebTestBase {
*
* @var array
*/
public static $modules = array('entity_reference', 'field_ui', 'node');
public static $modules = ['field_ui', 'node'];
/**
* A user with permission to administer content types, node fields, etc.

View File

@ -2,10 +2,10 @@
/**
* @file
* Contains \Drupal\entity_reference\Tests\EntityReferenceFieldTranslatedReferenceViewTest.
* Contains \Drupal\field\Tests\EntityReference\EntityReferenceFieldTranslatedReferenceViewTest.
*/
namespace Drupal\entity_reference\Tests;
namespace Drupal\field\Tests\EntityReference;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
@ -117,7 +117,6 @@ class EntityReferenceFieldTranslatedReferenceViewTest extends WebTestBase {
public static $modules = array(
'language',
'content_translation',
'entity_reference',
'node',
);

View File

@ -2,10 +2,10 @@
/**
* @file
* Contains \Drupal\entity_reference\Tests\EntityReferenceFileUploadTest.
* Contains \Drupal\field\Tests\EntityReference\EntityReferenceFileUploadTest.
*/
namespace Drupal\entity_reference\Tests;
namespace Drupal\field\Tests\EntityReference;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\simpletest\WebTestBase;

View File

@ -10,7 +10,6 @@ namespace Drupal\field\Tests\EntityReference;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\filter\Entity\FilterFormat;
use Drupal\system\Tests\Entity\EntityUnitTestBase;
@ -62,13 +61,6 @@ class EntityReferenceFormatterTest extends EntityUnitTestBase {
*/
protected $unsavedReferencedEntity;
/**
* Modules to install.
*
* @var array
*/
public static $modules = array('entity_reference');
protected function setUp() {
parent::setUp();

View File

@ -2,15 +2,14 @@
/**
* @file
* Contains \Drupal\entity_reference\Tests\EntityReferenceIntegrationTest.
* Contains \Drupal\field\Tests\EntityReference\EntityReferenceIntegrationTest.
*/
namespace Drupal\entity_reference\Tests;
namespace Drupal\field\Tests\EntityReference;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\config\Tests\AssertConfigEntityImportTrait;
use Drupal\Core\Config\Entity\ConfigEntityBase;
use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
use Drupal\field\Entity\FieldConfig;
use Drupal\simpletest\WebTestBase;
@ -50,7 +49,7 @@ class EntityReferenceIntegrationTest extends WebTestBase {
*
* @var array
*/
public static $modules = array('config_test', 'entity_test', 'entity_reference', 'field_ui');
public static $modules = ['config_test', 'entity_test', 'field_ui'];
/**
* {@inheritdoc}

View File

@ -13,7 +13,6 @@ use Drupal\Core\Field\FieldItemInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\Language\LanguageInterface;
use Drupal\entity_test\Entity\EntityTest;
use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
use Drupal\entity_test\Entity\EntityTestStringId;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
@ -36,7 +35,7 @@ class EntityReferenceItemTest extends FieldUnitTestBase {
*
* @var array
*/
public static $modules = array('entity_reference', 'taxonomy', 'text', 'filter', 'views');
public static $modules = ['taxonomy', 'text', 'filter', 'views', 'field'];
/**
* The taxonomy vocabulary to test with.

View File

@ -2,10 +2,10 @@
/**
* @file
* Contains \Drupal\entity_reference\Tests\EntityReferenceSettingsTest.
* Contains \Drupal\field\Tests\EntityReference\EntityReferenceSettingsTest.
*/
namespace Drupal\entity_reference\Tests;
namespace Drupal\field\Tests\EntityReference;
use Drupal\Component\Utility\Unicode;
use Drupal\field\Entity\FieldConfig;
@ -16,7 +16,7 @@ use Drupal\taxonomy\Entity\Vocabulary;
/**
* Tests entity reference field settings.
*
* @group entity_reference
* @group field
*/
class EntityReferenceSettingsTest extends KernelTestBase {

View File

@ -2,10 +2,10 @@
/**
* @file
* Contains \Drupal\entity_reference\Tests\EntityReferenceTestTrait.
* Contains \Drupal\field\Tests\EntityReference\EntityReferenceTestTrait.
*/
namespace Drupal\entity_reference\Tests;
namespace Drupal\field\Tests\EntityReference;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;

View File

@ -2,10 +2,10 @@
/**
* @file
* Contains \Drupal\entity_reference\Tests\EntityReferenceXSSTest.
* Contains \Drupal\field\Tests\EntityReference\EntityReferenceXSSTest.
*/
namespace Drupal\entity_reference\Tests;
namespace Drupal\field\Tests\EntityReference;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\Core\Entity\Entity\EntityViewDisplay;
@ -25,7 +25,7 @@ class EntityReferenceXSSTest extends WebTestBase {
*
* @var array
*/
protected static $modules = ['node', 'entity_reference'];
protected static $modules = ['node'];
/**
* Tests markup is escaped in the entity reference select and label formatter.

View File

@ -2,12 +2,12 @@
/**
* @file
* Contains \Drupal\entity_reference\Tests\Views\EntityReferenceRelationshipTest.
* Contains \Drupal\field\Tests\EntityReference\Views\EntityReferenceRelationshipTest.
*/
namespace Drupal\entity_reference\Tests\Views;
namespace Drupal\field\Tests\EntityReference\Views;
use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\entity_test\Entity\EntityTest;
use Drupal\entity_test\Entity\EntityTestMul;
use Drupal\views\Tests\ViewTestData;
@ -18,7 +18,8 @@ use Drupal\views\Views;
* Tests entity reference relationship data.
*
* @group entity_reference
* @see entity_reference_field_views_data()
*
* @see core_field_views_data()
*/
class EntityReferenceRelationshipTest extends ViewKernelTestBase {
@ -41,7 +42,7 @@ class EntityReferenceRelationshipTest extends ViewKernelTestBase {
*
* @var array
*/
public static $modules = array('user', 'field', 'entity_test', 'entity_reference', 'views', 'entity_reference_test_views');
public static $modules = ['user', 'field', 'entity_test', 'views', 'entity_reference_test_views'];
/**
* The entity_test entities used by the test.

View File

@ -2,10 +2,10 @@
/**
* @file
* Contains \Drupal\entity_reference\Tests\Views\SelectionTest.
* Contains \Drupal\field\Tests\EntityReference\Views\SelectionTest.
*/
namespace Drupal\entity_reference\Tests\Views;
namespace Drupal\field\Tests\EntityReference\Views;
use Drupal\simpletest\WebTestBase;
use Drupal\views\Views;
@ -17,7 +17,7 @@ use Drupal\views\Views;
*/
class SelectionTest extends WebTestBase {
public static $modules = array('node', 'views', 'entity_reference', 'entity_reference_test', 'entity_test');
public static $modules = ['node', 'views', 'entity_reference_test', 'entity_test'];
/**
* Nodes for testing.

View File

@ -22,7 +22,7 @@ abstract class FieldUnitTestBase extends KernelTestBase {
*
* @var array
*/
public static $modules = array('user', 'system', 'field', 'text', 'entity_test', 'field_test', 'entity_reference');
public static $modules = ['user', 'system', 'field', 'text', 'entity_test', 'field_test'];
/**
* Bag of created field storages and fields.

View File

@ -24,7 +24,6 @@ class MigrateFieldFormatterSettingsTest extends MigrateDrupal7TestBase {
public static $modules = [
'comment',
'datetime',
'entity_reference',
'file',
'image',
'link',

View File

@ -28,7 +28,6 @@ class MigrateFieldInstanceTest extends MigrateDrupal7TestBase {
static $modules = array(
'comment',
'datetime',
'entity_reference',
'file',
'image',
'link',

View File

@ -26,7 +26,6 @@ class MigrateFieldInstanceWidgetSettingsTest extends MigrateDrupal7TestBase {
public static $modules = array(
'comment',
'datetime',
'entity_reference',
'field',
'file',
'image',

View File

@ -27,7 +27,6 @@ class MigrateFieldTest extends MigrateDrupal7TestBase {
static $modules = array(
'comment',
'datetime',
'entity_reference',
'file',
'image',
'link',

View File

@ -1,53 +0,0 @@
<?php
/**
* @file
* Contains \Drupal\field\Tests\Update\EntityReferenceTargetBundleUpdateTest.
*/
namespace Drupal\field\Tests\Update;
use Drupal\system\Tests\Update\UpdatePathTestBase;
/**
* Tests that field settings are properly updated during database updates.
*
* @group field
*/
class EntityReferenceTargetBundleUpdateTest extends UpdatePathTestBase {
/**
* {@inheritdoc}
*/
protected function setDatabaseDumpFiles() {
$this->databaseDumpFiles = [
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
];
}
/**
* Tests field_update_8001().
*
* @see field_update_8001()
*/
public function testFieldUpdate8001() {
$configFactory = $this->container->get('config.factory');
// Load the 'node.field_image' field storage config, and check that is has
// a 'target_bundle' setting.
/** @var \Drupal\Core\Config\Config */
$config = $configFactory->get('field.storage.node.field_image');
$settings = $config->get('settings');
$this->assertTrue(array_key_exists('target_bundle', $settings));
// Run updates.
$this->runUpdates();
// Reload the config, and check that the 'target_bundle' setting has been
// removed.
$config = $configFactory->get('field.storage.node.field_image');
$settings = $config->get('settings');
$this->assertFalse(array_key_exists('target_bundle', $settings));
}
}

View File

@ -0,0 +1,128 @@
<?php
/**
* @file
* Contains \Drupal\field\Tests\Update\FieldUpdateTest.
*/
namespace Drupal\field\Tests\Update;
use Drupal\Core\Config\Config;
use Drupal\field\Entity\FieldConfig;
use Drupal\node\Entity\Node;
use Drupal\system\Tests\Update\UpdatePathTestBase;
/**
* Tests that field settings are properly updated during database updates.
*
* @group field
*/
class FieldUpdateTest extends UpdatePathTestBase {
/**
* The config factory service.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->configFactory = $this->container->get('config.factory');
}
/**
* {@inheritdoc}
*/
protected function setDatabaseDumpFiles() {
$this->databaseDumpFiles = [
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
__DIR__ . '/../../../tests/fixtures/update/drupal-8.views_entity_reference_plugins-2429191.php',
];
}
/**
* Tests field_update_8001().
*
* @see field_update_8001()
*/
public function testFieldUpdate8001() {
// Load the 'node.field_image' field storage config, and check that is has
// a 'target_bundle' setting.
$config = $this->configFactory->get('field.storage.node.field_image');
$settings = $config->get('settings');
$this->assertTrue(array_key_exists('target_bundle', $settings));
// Run updates.
$this->runUpdates();
// Reload the config, and check that the 'target_bundle' setting has been
// removed.
$config = $this->configFactory->get('field.storage.node.field_image');
$settings = $config->get('settings');
$this->assertFalse(array_key_exists('target_bundle', $settings));
}
/**
* Tests field_update_8002().
*
* @see field_update_8002()
*/
public function testFieldUpdate8002() {
// Check that 'entity_reference' is the provider and a dependency of the
// test field storage .
$field_storage = $this->configFactory->get('field.storage.node.field_ref_views_select_2429191');
$this->assertIdentical($field_storage->get('module'), 'entity_reference');
$this->assertEntityRefDependency($field_storage, TRUE);
// Check that 'entity_reference' is a dependency of the test field.
$field = $this->configFactory->get('field.field.node.article.field_ref_views_select_2429191');
$this->assertEntityRefDependency($field, TRUE);
// Check that 'entity_reference' is a dependency of the test view.
$view = $this->configFactory->get('views.view.entity_reference_plugins_2429191');
$this->assertEntityRefDependency($view, TRUE);
// Run updates.
$this->runUpdates();
// Check that 'entity_reference' is no longer a dependency of the test field
// and view.
$field_storage = $this->configFactory->get('field.storage.node.field_ref_views_select_2429191');
$this->assertIdentical($field_storage->get('module'), 'core');
$this->assertEntityRefDependency($field_storage, FALSE);
$field = $this->configFactory->get('field.field.node.article.field_ref_views_select_2429191');
$this->assertEntityRefDependency($field, FALSE);
$view = $this->configFactory->get('views.view.entity_reference_plugins_2429191');
$this->assertEntityRefDependency($view, FALSE);
// Check that field selection, based on the view, still works. It only
// selects nodes whose title contains 'foo'.
$node_1 = Node::create(['type' => 'article', 'title' => 'foobar']);
$node_1->save();
$node_2 = Node::create(['type' => 'article', 'title' => 'barbaz']);
$node_2->save();
$field = FieldConfig::load('node.article.field_ref_views_select_2429191');
$selection = \Drupal::service('plugin.manager.entity_reference_selection')->getSelectionHandler($field);
$referencable = $selection->getReferenceableEntities();
$this->assertEqual(array_keys($referencable['article']), [$node_1->id()]);
}
/**
* Asserts that a config depends on 'entity_reference' or not
*
* @param \Drupal\Core\Config\Config $config
* The config to test.
* @param bool $present
* TRUE to test that entity_reference is present, FALSE to test that it is
* absent.
*/
protected function assertEntityRefDependency(Config $config, $present) {
$dependencies = $config->get('dependencies');
$dependencies += ['module' => []];
$this->assertEqual(in_array('entity_reference', $dependencies['module']), $present);
}
}

View File

@ -0,0 +1,73 @@
<?php
/**
* @file
* Contains database additions to drupal-8.bare.standard.php.gz for testing the
* upgrade path of https://www.drupal.org/node/2429191.
*/
use Drupal\Core\Database\Database;
use Drupal\Component\Serialization\Yaml;
$connection = Database::getConnection();
// Configuration for a View with an "entity_reference selection" display.
$config = Yaml::decode(file_get_contents(__DIR__ . '/views.view.entity_reference_plugins_2429191.yml'));
$connection->insert('config')
->fields([
'collection',
'name',
'data',
])
->values([
'collection' => '',
'name' => 'views.view.' . $config['id'],
'data' => serialize($config),
])
->execute();
// Configuration for an entity_reference field storage.
$config = Yaml::decode(file_get_contents(__DIR__ . '/field.storage.node.field_ref_views_select_2429191.yml'));
$connection->insert('config')
->fields([
'collection',
'name',
'data',
])
->values([
'collection' => '',
'name' => 'field.storage.' . $config['id'],
'data' => serialize($config),
])
->execute();
// We need to Update the registry of "last installed" field definitions.
$installed = $connection->select('key_value')
->fields('key_value', ['value'])
->condition('collection', 'entity.definitions.installed')
->condition('name', 'node.field_storage_definitions')
->execute()
->fetchField();
$installed = unserialize($installed);
$installed['field_ref_views_select_2429191'] = new \Drupal\field\Entity\FieldStorageConfig($config);
$connection->update('key_value')
->condition('collection', 'entity.definitions.installed')
->condition('name', 'node.field_storage_definitions')
->fields([
'value' => serialize($installed)
])
->execute();
// Configuration for an entity_reference field using the View for selection.
$config = Yaml::decode(file_get_contents(__DIR__ . '/field.field.node.article.field_ref_views_select_2429191.yml'));
$connection->insert('config')
->fields([
'collection',
'name',
'data',
])
->values([
'collection' => '',
'name' => 'field.field.' . $config['id'],
'data' => serialize($config),
])
->execute();

View File

@ -0,0 +1,27 @@
uuid: ac77b88d-dfa0-4b07-b700-ba50cb51f72a
langcode: en
status: true
dependencies:
config:
- field.storage.node.field_ref_views_select_2429191
- node.type.article
module:
- entity_reference
id: node.article.field_ref_views_select_2429191
field_name: field_ref_views_select_2429191
entity_type: node
bundle: article
label: reference_views_select
description: ''
required: false
translatable: false
default_value: { }
default_value_callback: ''
settings:
handler: views
handler_settings:
view:
view_name: entity_reference_plugins_2429191
display_name: entity_reference_1
arguments: { }
field_type: entity_reference

View File

@ -0,0 +1,19 @@
uuid: 7f5e9177-56b3-4b84-a936-54bfd4d4c078
langcode: en
status: true
dependencies:
module:
- entity_reference
- node
id: node.field_ref_views_select_2429191
field_name: field_ref_views_select_2429191
entity_type: node
type: entity_reference
settings:
target_type: node
module: entity_reference
locked: false
cardinality: 1
translatable: true
indexes: { }
persist_with_no_fields: false

View File

@ -0,0 +1,214 @@
uuid: 8b3d9ae1-c8f9-4219-af35-53f687e6081b
langcode: en
status: true
dependencies:
module:
- entity_reference
- node
- user
id: entity_reference_plugins_2429191
label: test
module: views
description: ''
tag: ''
base_table: node_field_data
base_field: nid
core: 8.x
display:
default:
display_plugin: default
id: default
display_title: Master
position: 0
display_options:
access:
type: perm
options:
perm: 'access content'
cache:
type: tag
options: { }
query:
type: views_query
options:
disable_sql_rewrite: false
distinct: false
replica: false
query_comment: ''
query_tags: { }
exposed_form:
type: basic
options:
submit_button: Apply
reset_button: false
reset_button_label: Reset
exposed_sorts_label: 'Sort by'
expose_sort_order: true
sort_asc_label: Asc
sort_desc_label: Desc
pager:
type: full
options:
items_per_page: 10
offset: 0
id: 0
total_pages: null
expose:
items_per_page: false
items_per_page_label: 'Items per page'
items_per_page_options: '5, 10, 25, 50'
items_per_page_options_all: false
items_per_page_options_all_label: '- All -'
offset: false
offset_label: Offset
tags:
previous: ' previous'
next: 'next '
first: '« first'
last: 'last »'
quantity: 9
style:
type: default
options:
grouping: { }
row_class: ''
default_row_class: true
uses_fields: false
row:
type: fields
options:
inline: { }
separator: ''
hide_empty: false
default_field_elements: true
fields:
title:
id: title
table: node_field_data
field: title
entity_type: node
entity_field: title
label: ''
alter:
alter_text: false
make_link: false
absolute: false
trim: false
word_boundary: false
ellipsis: false
strip_tags: false
html: false
hide_empty: false
empty_zero: false
settings:
link_to_entity: true
plugin_id: field
relationship: none
group_type: group
admin_label: ''
exclude: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: true
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_alter_empty: true
click_sort_column: value
type: string
group_column: value
group_columns: { }
group_rows: true
delta_limit: 0
delta_offset: 0
delta_reversed: false
delta_first_last: false
multi_type: separator
separator: ', '
field_api_classes: false
filters:
status:
value: true
table: node_field_data
field: status
plugin_id: boolean
entity_type: node
entity_field: status
id: status
expose:
operator: ''
group: 1
title:
id: title
table: node_field_data
field: title
relationship: none
group_type: group
admin_label: ''
operator: contains
value: foo
group: 1
exposed: false
expose:
operator_id: ''
label: ''
description: ''
multiple: false
remember: false
entity_type: node
entity_field: title
plugin_id: string
sorts:
created:
id: created
table: node_field_data
field: created
order: DESC
entity_type: node
entity_field: created
plugin_id: date
relationship: none
group_type: group
admin_label: ''
exposed: false
expose:
label: ''
granularity: second
header: { }
footer: { }
empty: { }
relationships: { }
arguments: { }
display_extenders: { }
cache_metadata:
max-age: -1
contexts:
- 'languages:language_content'
- 'languages:language_interface'
- url.query_args
- 'user.node_grants:view'
- user.permissions
tags: { }
entity_reference_1:
display_plugin: entity_reference
id: entity_reference_1
display_title: 'Entity Reference'
position: 1
display_options:
display_extenders: { }
style:
type: entity_reference
options:
search_fields:
title: title
cache_metadata:
max-age: -1
contexts:
- 'languages:language_content'
- 'languages:language_interface'
- 'user.node_grants:view'
- user.permissions
tags: { }

View File

@ -99,7 +99,7 @@ class TestFieldWidgetMultiple extends WidgetBase {
/**
* {@inheritdoc}
* Used in \Drupal\entity_reference\Tests\EntityReferenceAdminTest::testAvailableFormatters().
* Used in \Drupal\field\Tests\EntityReference\EntityReferenceAdminTest::testAvailableFormatters().
*/
public static function isApplicable(FieldDefinitionInterface $field_definition) {
// Returns FALSE if machine name of the field equals field_onewidgetfield.

View File

@ -297,3 +297,14 @@ function field_ui_local_tasks_alter(&$local_tasks) {
$local_task = FieldUiLocalTask::create($container, 'field_ui.fields');
$local_task->alterLocalTasks($local_tasks);
}
/**
* Implements hook_form_FORM_ID_alter() for 'field_ui_field_storage_add_form'.
*/
function field_ui_form_field_ui_field_storage_add_form_alter(array &$form) {
$optgroup = (string) t('Reference');
// Move the "Entity reference" option to the end of the list and rename it to
// "Other".
unset($form['add']['new_storage_type']['#options'][$optgroup]['entity_reference']);
$form['add']['new_storage_type']['#options'][$optgroup]['entity_reference'] = t('Other…');
}

View File

@ -25,7 +25,7 @@ class EntityFormDisplayTest extends KernelTestBase {
*
* @var string[]
*/
public static $modules = array('field_ui', 'field', 'entity_test', 'field_test', 'user', 'text', 'entity_reference');
public static $modules = ['field_ui', 'field', 'entity_test', 'field_test', 'user', 'text'];
protected function setUp() {
parent::setUp();

View File

@ -10,7 +10,7 @@ namespace Drupal\field_ui\Tests;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\simpletest\WebTestBase;

View File

@ -340,4 +340,11 @@ class FileItem extends EntityReferenceItem {
return TRUE;
}
/**
* {@inheritdoc}
*/
public static function getPreconfiguredOptions() {
return [];
}
}

View File

@ -8,7 +8,6 @@ dependencies:
- node.type.forum
module:
- comment
- entity_reference
- text
id: node.forum.default
targetEntityType: node

View File

@ -10,7 +10,7 @@ entity_type: node
type: entity_reference
settings:
target_type: taxonomy_term
module: entity_reference
module: core
locked: false
cardinality: 1
translatable: true

View File

@ -23,7 +23,6 @@ class MigrateForumSettingsTest extends MigrateDrupal7TestBase {
'comment',
'field',
'filter',
'entity_reference',
'text',
'node',
'taxonomy',

View File

@ -33,7 +33,7 @@ abstract class NormalizerTestBase extends KernelTestBase {
*
* @var array
*/
public static $modules = array('entity_test', 'entity_reference', 'field', 'hal', 'language', 'rest', 'serialization', 'system', 'text', 'user', 'filter');
public static $modules = ['entity_test', 'field', 'hal', 'language', 'rest', 'serialization', 'system', 'text', 'user', 'filter'];
/**
* The mock serializer.

View File

@ -20,7 +20,6 @@ abstract class MigrateDrupal6TestBase extends MigrateDrupalTestBase {
*/
public static $modules = [
'datetime',
'entity_reference',
'filter',
'image',
'link',

View File

@ -7,4 +7,3 @@ core: 8.x
configure: entity.node_type.collection
dependencies:
- text
- entity_reference

View File

@ -22,7 +22,7 @@ class NodeImportChangeTest extends KernelTestBase {
*
* @var array
*/
public static $modules = array('node', 'field', 'text', 'system', 'node_test_config', 'user', 'entity_reference');
public static $modules = ['node', 'field', 'text', 'system', 'node_test_config', 'user'];
/**
* Set the default field storage backend for fields created during tests.

View File

@ -23,7 +23,7 @@ class NodeImportCreateTest extends KernelTestBase {
*
* @var array
*/
public static $modules = array('node', 'field', 'text', 'system', 'user', 'entity_reference');
public static $modules = array('node', 'field', 'text', 'system', 'user');
/**
* Set the default field storage backend for fields created during tests.

View File

@ -21,7 +21,6 @@ class MigrateNodeTest extends MigrateDrupal7TestBase {
static $modules = array(
'comment',
'datetime',
'entity_reference',
'filter',
'image',
'link',

View File

@ -27,7 +27,7 @@ class NodeBodyFieldStorageTest extends KernelTestBase {
*
* @var array
*/
public static $modules = array('user', 'system', 'field', 'node', 'text', 'filter', 'entity_reference');
public static $modules = ['user', 'system', 'field', 'node', 'text', 'filter'];
protected function setUp() {
parent::setUp();

View File

@ -11,7 +11,7 @@ use Drupal\comment\Tests\CommentTestTrait;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Language\LanguageInterface;
use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\node\Entity\NodeType;

View File

@ -23,7 +23,7 @@ class NidArgumentTest extends ViewKernelTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['node', 'field', 'text', 'node_test_config', 'user', 'entity_reference', 'node_test_views'];
public static $modules = ['node', 'field', 'text', 'node_test_config', 'user', 'node_test_views'];
/**
* Views used by this test.

View File

@ -5,7 +5,6 @@ dependencies:
- field.field.node.options_install_test.body
- node.type.options_install_test
module:
- entity_reference
- text
id: node.options_install_test.default
targetEntityType: node

View File

@ -10,7 +10,7 @@ namespace Drupal\quickedit\Tests;
use Drupal\Component\Serialization\Json;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\simpletest\WebTestBase;
/**

View File

@ -19,7 +19,7 @@ abstract class QuickEditTestBase extends KernelTestBase {
*
* @var array
*/
public static $modules = array('system', 'entity_test', 'field', 'field_test', 'filter', 'user', 'text', 'quickedit', 'entity_reference');
public static $modules = ['system', 'entity_test', 'field', 'field_test', 'filter', 'user', 'text', 'quickedit'];
/**
* Bag of created fields.

View File

@ -6,7 +6,7 @@
namespace Drupal\rdf\Tests\Field;
use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\user\Entity\Role;
use Drupal\user\RoleInterface;
@ -48,7 +48,7 @@ class EntityReferenceRdfaTest extends FieldRdfaTestBase {
/**
* {@inheritdoc}
*/
public static $modules = array('entity_reference', 'text', 'filter');
public static $modules = ['text', 'filter'];
protected function setUp() {
parent::setUp();

View File

@ -20,7 +20,7 @@ class EntityResolverTest extends NormalizerTestBase {
*
* @var array
*/
public static $modules = array('entity_reference', 'hal', 'rest');
public static $modules = ['hal', 'rest'];
/**
* The format being tested.

View File

@ -29,7 +29,7 @@ abstract class EntityCacheTagsTestBase extends PageCacheTagsTestBase {
*
* @var array
*/
public static $modules = array('entity_reference', 'entity_test', 'field_test');
public static $modules = ['entity_test', 'field_test'];
/**
* The main entity used for testing.

View File

@ -7,7 +7,7 @@
namespace Drupal\system\Tests\Entity;
use Drupal\Component\Utility\Unicode;
use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
/**
* Tests the Entity Query relationship API.

View File

@ -12,7 +12,7 @@ use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\field\Entity\FieldConfig;
use Drupal\user\Entity\Role;
use Drupal\user\Entity\User;

View File

@ -20,7 +20,7 @@ abstract class EntityUnitTestBase extends KernelTestBase {
*
* @var array
*/
public static $modules = array('user', 'system', 'field', 'text', 'filter', 'entity_test', 'entity_reference');
public static $modules = ['user', 'system', 'field', 'text', 'filter', 'entity_test'];
/**
* The entity manager service.

View File

@ -8,7 +8,7 @@
namespace Drupal\system\Tests\Entity;
use Drupal\Core\Language\LanguageInterface;
use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\Core\Cache\Cache;
use Drupal\user\Entity\Role;
use Drupal\user\RoleInterface;
@ -22,13 +22,6 @@ class EntityViewBuilderTest extends EntityUnitTestBase {
use EntityReferenceTestTrait;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('entity_reference');
/**
* {@inheritdoc}
*/

View File

@ -22,7 +22,7 @@ class FieldAccessTest extends KernelTestBase {
*
* @var array
*/
public static $modules = array('entity_test', 'field', 'system', 'text', 'filter', 'user', 'entity_reference');
public static $modules = ['entity_test', 'field', 'system', 'text', 'filter', 'user'];
/**
* Holds the currently active global user ID that initiated the test run.

View File

@ -358,7 +358,6 @@ class UpdatePathTestBaseFilledTest extends UpdatePathTestBaseTest {
'datetime',
'dblog',
'editor',
'entity_reference',
'field',
'field_ui',
'file',

View File

@ -9,6 +9,7 @@ use Drupal\Component\Render\PlainTextOutput;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Asset\AttachedAssetsInterface;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Database\Query\AlterableInterface;
use Drupal\Core\Extension\Extension;
use Drupal\Core\Extension\ExtensionDiscovery;
use Drupal\Core\Form\FormStateInterface;
@ -1424,3 +1425,11 @@ function system_path_insert() {
function system_path_delete($path) {
\Drupal::service('path.alias_manager')->cacheClear();
}
/**
* Implements hook_query_TAG_alter() for entity reference selection handlers.
*/
function system_query_entity_reference_alter(AlterableInterface $query) {
$handler = $query->getMetadata('entity_reference_selection_handler');
$handler->entityQueryAlter($query);
}

View File

@ -2,7 +2,6 @@ langcode: en
status: true
dependencies:
module:
- entity_reference
- entity_reference_test
- entity_test
id: test_entity_reference_entity_test

View File

@ -5,7 +5,6 @@ core: 8.x
package: Testing
version: VERSION
dependencies:
- entity_reference
- node
- user
- views

View File

@ -7,4 +7,3 @@ core: 8.x
dependencies:
- field
- text
- entity_reference

View File

@ -9,7 +9,7 @@ namespace Drupal\Tests\system\Kernel\Entity;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\Unicode;
use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\field\Entity\FieldConfig;
use Drupal\node\Entity\NodeType;
use Drupal\KernelTests\KernelTestBase;

View File

@ -21,7 +21,6 @@ class MigrateNodeTaxonomyTest extends MigrateDrupal7TestBase {
public static $modules = array(
'datetime',
'entity_reference',
'field',
'filter',
'image',

View File

@ -7,7 +7,7 @@
namespace Drupal\taxonomy\Tests;
use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\simpletest\WebTestBase;
/**

View File

@ -8,7 +8,7 @@
namespace Drupal\taxonomy\Tests;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\language\Entity\ConfigurableLanguage;

View File

@ -22,7 +22,7 @@ class TermEntityReferenceTest extends TaxonomyTestBase {
*
* @var array
*/
public static $modules = array('entity_reference', 'entity_reference_test', 'entity_test');
public static $modules = ['entity_reference_test', 'entity_test'];
/**
* Tests an entity reference field restricted to a single vocabulary.

View File

@ -8,7 +8,7 @@
namespace Drupal\taxonomy\Tests\Views;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\taxonomy\Entity\Term;
use Drupal\taxonomy\Entity\Vocabulary;
use Drupal\views\Tests\ViewTestData;
@ -36,7 +36,7 @@ class TaxonomyIndexTidUiTest extends UITestBase {
*
* @var array
*/
public static $modules = array('node', 'taxonomy', 'taxonomy_test_views', 'entity_reference');
public static $modules = ['node', 'taxonomy', 'taxonomy_test_views'];
/**
* A nested array of \Drupal\taxonomy\TermInterface objects.

View File

@ -9,7 +9,7 @@ namespace Drupal\taxonomy\Tests\Views;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\views\Tests\ViewTestBase;
use Drupal\views\Tests\ViewTestData;

View File

@ -5,7 +5,6 @@ package: Core
version: VERSION
core: 8.x
dependencies:
- entity_reference
- node
- text
configure: entity.taxonomy_vocabulary.collection

View File

@ -501,9 +501,12 @@ function taxonomy_build_node_index($node) {
if ($status && $node->isDefaultRevision()) {
// Collect a unique list of all the term IDs from all node fields.
$tid_all = array();
$entity_reference_class = 'Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem';
foreach ($node->getFieldDefinitions() as $field) {
$field_name = $field->getName();
if (is_subclass_of($field->getItemDefinition()->getClass(), '\Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem') && $field->getSetting('target_type') == 'taxonomy_term') {
$class = $field->getItemDefinition()->getClass();
$is_entity_reference_class = ($class === $entity_reference_class) || is_subclass_of($class, $entity_reference_class);
if ($is_entity_reference_class && $field->getSetting('target_type') == 'taxonomy_term') {
foreach ($node->getTranslationLanguages() as $language) {
foreach ($node->getTranslation($language->getId())->$field_name as $item) {
if (!$item->isEmpty()) {

View File

@ -21,7 +21,6 @@ class MigrateTrackerNodeTest extends MigrateDrupal7TestBase {
* {@inheritdoc}
*/
public static $modules = [
'entity_reference',
'node',
'text',
'tracker',

View File

@ -21,7 +21,6 @@ class MigrateTrackerUserTest extends MigrateDrupal7TestBase {
* {@inheritdoc}
*/
public static $modules = [
'entity_reference',
'node',
'text',
'tracker',

View File

@ -120,7 +120,7 @@ class UserSelection extends DefaultSelection {
$form['filter']['settings'] = array(
'#type' => 'container',
'#attributes' => array('class' => array('entity_reference-settings')),
'#process' => array('_entity_reference_form_process_merge_parent'),
'#process' => array(array('\Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem', 'formProcessMergeParent')),
);
if ($selection_handler_settings['filter']['type'] == 'role') {

View File

@ -7,7 +7,7 @@
namespace Drupal\user\Tests;
use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\field\Entity\FieldConfig;
use Drupal\system\Tests\Entity\EntityUnitTestBase;
@ -34,13 +34,6 @@ class UserEntityReferenceTest extends EntityUnitTestBase {
*/
protected $role2;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('entity_reference', 'user');
/**
* {@inheritdoc}
*/

Some files were not shown because too many files have changed in this diff Show More