updated core from 8.4 to 8.5 : bug with login_destination

This commit is contained in:
Bachir Soussi Chiadmi
2018-03-13 14:01:21 +01:00
parent 0d78da249b
commit e668535a4e
3486 changed files with 89604 additions and 33283 deletions
+107
View File
@@ -58,6 +58,33 @@ function hook_field_info_alter(&$info) {
}
}
/**
* Perform alterations on preconfigured field options.
*
* @param array $options
* Array of options as returned from
* \Drupal\Core\Field\PreconfiguredFieldUiOptionsInterface::getPreconfiguredOptions().
* @param string $field_type
* The field type plugin ID.
*
* @see \Drupal\Core\Field\PreconfiguredFieldUiOptionsInterface::getPreconfiguredOptions()
*/
function hook_field_ui_preconfigured_options_alter(array &$options, $field_type) {
// If the field is not an "entity_reference"-based field, bail out.
/** @var \Drupal\Core\Field\FieldTypePluginManager $field_type_manager */
$field_type_manager = \Drupal::service('plugin.manager.field.field_type');
$class = $field_type_manager->getPluginClass($field_type);
if (!is_a($class, 'Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem', TRUE)) {
return;
}
// Set the default formatter for media in entity reference fields to be the
// "Rendered entity" formatter.
if (!empty($options['media'])) {
$options['media']['entity_view_display']['type'] = 'entity_reference_entity_view';
}
}
/**
* Forbid a field storage update from occurring.
*
@@ -137,6 +164,11 @@ function hook_field_widget_info_alter(array &$info) {
/**
* Alter forms for field widgets provided by other modules.
*
* This hook can only modify individual elements within a field widget and
* cannot alter the top level (parent element) for multi-value fields. In most
* cases, you should use hook_field_widget_multivalue_form_alter() instead and
* loop over the elements.
*
* @param $element
* The field widget form element as constructed by
* \Drupal\Core\Field\WidgetBaseInterface::form().
@@ -156,6 +188,7 @@ function hook_field_widget_info_alter(array &$info) {
* @see \Drupal\Core\Field\WidgetBaseInterface::form()
* @see \Drupal\Core\Field\WidgetBase::formSingleElement()
* @see hook_field_widget_WIDGET_TYPE_form_alter()
* @see hook_field_widget_multivalue_form_alter()
*/
function hook_field_widget_form_alter(&$element, \Drupal\Core\Form\FormStateInterface $form_state, $context) {
// Add a css class to widget form elements for all fields of type mytype.
@@ -173,6 +206,11 @@ function hook_field_widget_form_alter(&$element, \Drupal\Core\Form\FormStateInte
* specific widget form, rather than using hook_field_widget_form_alter() and
* checking the widget type.
*
* This hook can only modify individual elements within a field widget and
* cannot alter the top level (parent element) for multi-value fields. In most
* cases, you should use hook_field_widget_multivalue_WIDGET_TYPE_form_alter()
* instead and loop over the elements.
*
* @param $element
* The field widget form element as constructed by
* \Drupal\Core\Field\WidgetBaseInterface::form().
@@ -185,6 +223,7 @@ function hook_field_widget_form_alter(&$element, \Drupal\Core\Form\FormStateInte
* @see \Drupal\Core\Field\WidgetBaseInterface::form()
* @see \Drupal\Core\Field\WidgetBase::formSingleElement()
* @see hook_field_widget_form_alter()
* @see hook_field_widget_multivalue_WIDGET_TYPE_form_alter()
*/
function hook_field_widget_WIDGET_TYPE_form_alter(&$element, \Drupal\Core\Form\FormStateInterface $form_state, $context) {
// Code here will only act on widgets of type WIDGET_TYPE. For example,
@@ -193,6 +232,74 @@ function hook_field_widget_WIDGET_TYPE_form_alter(&$element, \Drupal\Core\Form\F
$element['#autocomplete_route_name'] = 'mymodule.autocomplete_route';
}
/**
* Alter forms for multi-value field widgets provided by other modules.
*
* To alter the individual elements within the widget, loop over
* \Drupal\Core\Render\Element::children($elements).
*
* @param array $elements
* The field widget form elements as constructed by
* \Drupal\Core\Field\WidgetBase::formMultipleElements().
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
* @param array $context
* An associative array containing the following key-value pairs:
* - form: The form structure to which widgets are being attached. This may be
* a full form structure, or a sub-element of a larger form.
* - widget: The widget plugin instance.
* - items: The field values, as a
* \Drupal\Core\Field\FieldItemListInterface object.
* - default: A boolean indicating whether the form is being shown as a dummy
* form to set default values.
*
* @see \Drupal\Core\Field\WidgetBaseInterface::form()
* @see \Drupal\Core\Field\WidgetBase::formMultipleElements()
* @see hook_field_widget_multivalue_WIDGET_TYPE_form_alter()
*/
function hook_field_widget_multivalue_form_alter(array &$elements, \Drupal\Core\Form\FormStateInterface $form_state, array $context) {
// Add a css class to widget form elements for all fields of type mytype.
$field_definition = $context['items']->getFieldDefinition();
if ($field_definition->getType() == 'mytype') {
// Be sure not to overwrite existing attributes.
$elements['#attributes']['class'][] = 'myclass';
}
}
/**
* Alter multi-value widget forms for a widget provided by another module.
*
* Modules can implement hook_field_widget_multivalue_WIDGET_TYPE_form_alter() to
* modify a specific widget form, rather than using
* hook_field_widget_form_alter() and checking the widget type.
*
* To alter the individual elements within the widget, loop over
* \Drupal\Core\Render\Element::children($elements).
*
* @param array $elements
* The field widget form elements as constructed by
* \Drupal\Core\Field\WidgetBase::formMultipleElements().
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
* @param array $context
* An associative array. See hook_field_widget_multivalue_form_alter() for
* the structure and content of the array.
*
* @see \Drupal\Core\Field\WidgetBaseInterface::form()
* @see \Drupal\Core\Field\WidgetBase::formMultipleElements()
* @see hook_field_widget_multivalue_form_alter()
*/
function hook_field_widget_multivalue_WIDGET_TYPE_form_alter(array &$elements, \Drupal\Core\Form\FormStateInterface $form_state, array $context) {
// Code here will only act on widgets of type WIDGET_TYPE. For example,
// hook_field_widget_multivalue_mymodule_autocomplete_form_alter() will only
// act on widgets of type 'mymodule_autocomplete'.
// Change the autcomplete route for each autocomplete element within the
// multivalue widget.
foreach (Element::children($elements) as $delta => $element) {
$elements[$delta]['#autocomplete_route_name'] = 'mymodule.autocomplete_route';
}
}
/**
* @} End of "defgroup field_widget".
*/
+3 -3
View File
@@ -5,8 +5,8 @@ package: Core
# version: VERSION
# core: 8.x
# Information added by Drupal.org packaging script on 2018-01-03
version: '8.4.4'
# Information added by Drupal.org packaging script on 2018-03-07
version: '8.5.0'
core: '8.x'
project: 'drupal'
datestamp: 1515021228
datestamp: 1520457825
+29
View File
@@ -6,6 +6,8 @@
*/
use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
/**
* Removes the stale 'target_bundle' storage setting on entity_reference fields.
@@ -104,3 +106,30 @@ function field_update_8003() {
}
}
}
/**
* Update the definition of deleted fields.
*/
function field_update_8500() {
$state = \Drupal::state();
// Convert the old deleted field definitions from an array to a FieldConfig
// object.
$deleted_field_definitions = $state->get('field.field.deleted', []);
foreach ($deleted_field_definitions as $key => $deleted_field_definition) {
if (is_array($deleted_field_definition)) {
$deleted_field_definitions[$key] = new FieldConfig($deleted_field_definition);
}
}
$state->set('field.field.deleted', $deleted_field_definitions);
// Convert the old deleted field storage definitions from an array to a
// FieldStorageConfig object.
$deleted_field_storage_definitions = $state->get('field.storage.deleted', []);
foreach ($deleted_field_storage_definitions as $key => $deleted_field_storage_definition) {
if (is_array($deleted_field_storage_definition)) {
$deleted_field_storage_definitions[$key] = new FieldStorageConfig($deleted_field_storage_definition);
}
}
$state->set('field.storage.deleted', $deleted_field_storage_definitions);
}
+28 -35
View File
@@ -5,10 +5,9 @@
* Provides support for field data purge after mass deletion.
*/
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldException;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\field\FieldStorageConfigInterface;
use Drupal\field\FieldConfigInterface;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
/**
* @defgroup field_purge Field API bulk data deletion
@@ -67,20 +66,16 @@ use Drupal\field\FieldConfigInterface;
* be purged. If a deleted field storage with no remaining fields is found, the
* field storage itself will be purged.
*
* @param $batch_size
* @param int $batch_size
* The maximum number of field data records to purge before returning.
* @param string $field_storage_uuid
* (optional) Limit the purge to a specific field storage.
* @param string $field_storage_unique_id
* (optional) Limit the purge to a specific field storage. Defaults to NULL.
*/
function field_purge_batch($batch_size, $field_storage_uuid = NULL) {
$properties = [
'deleted' => TRUE,
'include_deleted' => TRUE,
];
if ($field_storage_uuid) {
$properties['field_storage_uuid'] = $field_storage_uuid;
}
$fields = entity_load_multiple_by_properties('field_config', $properties);
function field_purge_batch($batch_size, $field_storage_unique_id = NULL) {
/** @var \Drupal\Core\Field\DeletedFieldsRepositoryInterface $deleted_fields_repository */
$deleted_fields_repository = \Drupal::service('entity_field.deleted_fields_repository');
$fields = $deleted_fields_repository->getFieldDefinitions($field_storage_unique_id);
$info = \Drupal::entityManager()->getDefinitions();
foreach ($fields as $field) {
@@ -90,6 +85,7 @@ function field_purge_batch($batch_size, $field_storage_uuid = NULL) {
// providing module was uninstalled).
// @todo Revisit after https://www.drupal.org/node/2080823.
if (!isset($info[$entity_type])) {
\Drupal::logger('field')->warning("Cannot remove field @field_name because the entity type is unknown: %entity_type", ['@field_name' => $field->getName(), '%entity_type' => $entity_type]);
continue;
}
@@ -106,10 +102,8 @@ function field_purge_batch($batch_size, $field_storage_uuid = NULL) {
}
// Retrieve all deleted field storages. Any that have no fields can be purged.
$deleted_storages = \Drupal::state()->get('field.storage.deleted') ?: [];
foreach ($deleted_storages as $field_storage) {
$field_storage = new FieldStorageConfig($field_storage);
if ($field_storage_uuid && $field_storage->uuid() != $field_storage_uuid) {
foreach ($deleted_fields_repository->getFieldStorageDefinitions() as $field_storage) {
if ($field_storage_unique_id && $field_storage->getUniqueStorageIdentifier() != $field_storage_unique_id) {
// If a specific UUID is provided, only purge the corresponding field.
continue;
}
@@ -121,7 +115,7 @@ function field_purge_batch($batch_size, $field_storage_uuid = NULL) {
continue;
}
$fields = entity_load_multiple_by_properties('field_config', ['field_storage_uuid' => $field_storage->uuid(), 'include_deleted' => TRUE]);
$fields = $deleted_fields_repository->getFieldDefinitions($field_storage->getUniqueStorageIdentifier());
if (empty($fields)) {
field_purge_field_storage($field_storage);
}
@@ -134,14 +128,13 @@ function field_purge_batch($batch_size, $field_storage_uuid = NULL) {
* This function assumes all data for the field has already been purged and
* should only be called by field_purge_batch().
*
* @param $field
* The field record to purge.
* @param \Drupal\Core\Field\FieldDefinitionInterface $field
* The field to purge.
*/
function field_purge_field(FieldConfigInterface $field) {
$state = \Drupal::state();
$deleted_fields = $state->get('field.field.deleted');
unset($deleted_fields[$field->uuid()]);
$state->set('field.field.deleted', $deleted_fields);
function field_purge_field(FieldDefinitionInterface $field) {
/** @var \Drupal\Core\Field\DeletedFieldsRepositoryInterface $deleted_fields_repository */
$deleted_fields_repository = \Drupal::service('entity_field.deleted_fields_repository');
$deleted_fields_repository->removeFieldDefinition($field);
// Invoke external hooks after the cache is cleared for API consistency.
\Drupal::moduleHandler()->invokeAll('field_purge_field', [$field]);
@@ -153,21 +146,21 @@ function field_purge_field(FieldConfigInterface $field) {
* This function assumes all fields for the field storage has already been
* purged, and should only be called by field_purge_batch().
*
* @param \Drupal\field\FieldStorageConfigInterface $field_storage
* @param \Drupal\Core\Field\FieldStorageDefinitionInterface $field_storage
* The field storage to purge.
*
* @throws Drupal\field\FieldException
* @throws \Drupal\Core\Field\FieldException
*/
function field_purge_field_storage(FieldStorageConfigInterface $field_storage) {
$fields = entity_load_multiple_by_properties('field_config', ['field_storage_uuid' => $field_storage->uuid(), 'include_deleted' => TRUE]);
function field_purge_field_storage(FieldStorageDefinitionInterface $field_storage) {
/** @var \Drupal\Core\Field\DeletedFieldsRepositoryInterface $deleted_fields_repository */
$deleted_fields_repository = \Drupal::service('entity_field.deleted_fields_repository');
$fields = $deleted_fields_repository->getFieldDefinitions($field_storage->getUniqueStorageIdentifier());
if (count($fields) > 0) {
throw new FieldException(t('Attempt to purge a field storage @field_name that still has fields.', ['@field_name' => $field_storage->getName()]));
}
$state = \Drupal::state();
$deleted_storages = $state->get('field.storage.deleted');
unset($deleted_storages[$field_storage->uuid()]);
$state->set('field.storage.deleted', $deleted_storages);
$deleted_fields_repository->removeFieldStorageDefinition($field_storage);
// Notify the storage layer.
\Drupal::entityManager()->getStorage($field_storage->getTargetEntityTypeId())->finalizePurge($field_storage);
@@ -2,6 +2,7 @@ id: d6_field
label: Field configuration
migration_tags:
- Drupal 6
- Configuration
class: Drupal\migrate_drupal\Plugin\migrate\FieldMigration
field_plugin_method: processField
source:
@@ -2,6 +2,7 @@ id: d6_field_formatter_settings
label: Field formatter configuration
migration_tags:
- Drupal 6
- Configuration
class: Drupal\migrate_drupal\Plugin\migrate\FieldMigration
field_plugin_method: processFieldFormatter
source:
@@ -172,7 +173,7 @@ process:
default: entity_reference_label
plain: entity_reference_label
-
plugin: field_type_defaults
plugin: d6_field_type_defaults
"options/settings":
-
plugin: static_map
@@ -2,6 +2,7 @@ id: d6_field_instance
label: Field instance configuration
migration_tags:
- Drupal 6
- Configuration
class: Drupal\migrate_drupal\Plugin\migrate\FieldMigration
field_plugin_method: processFieldInstance
source:
@@ -2,6 +2,7 @@ id: d6_field_instance_widget_settings
label: Field instance widget configuration
migration_tags:
- Drupal 6
- Configuration
class: Drupal\migrate_drupal\Plugin\migrate\FieldMigration
field_plugin_method: processFieldWidget
source:
@@ -2,6 +2,7 @@ id: d7_field
label: Field configuration
migration_tags:
- Drupal 7
- Configuration
class: Drupal\migrate_drupal\Plugin\migrate\FieldMigration
field_plugin_method: processField
source:
@@ -2,6 +2,7 @@ id: d7_field_formatter_settings
label: Field formatter configuration
migration_tags:
- Drupal 7
- Configuration
class: Drupal\migrate_drupal\Plugin\migrate\FieldMigration
field_plugin_method: processFieldFormatter
source:
@@ -54,6 +55,11 @@ process:
field_name: field_name
"options/label": 'formatter/label'
"options/weight": 'formatter/weight'
# The field plugin ID.
plugin_id:
plugin: process_field
source: type
method: getPluginId
# The formatter to use.
formatter_type:
plugin: process_field
@@ -63,19 +69,14 @@ process:
-
plugin: static_map
bypass: true
source: '@formatter_type'
map:
date_default: datetime_default
email_default: email_mailto
# 0 should cause the row to be skipped by the next plugin in the
# pipeline.
hidden: 0
link_default: link
phone: basic_string
taxonomy_term_reference_link: entity_reference_label
entityreference_label: entity_reference_label
entityreference_entity_id: entity_reference_entity_id
entityreference_entity_view: entity_reference_entity_view
source:
- '@plugin_id'
- '@formatter_type'
# The map is generated by the getFieldFormatterMap() method from the
# migrate field plugins.
map: []
-
plugin: d7_field_type_defaults
-
plugin: skip_on_empty
method: row
@@ -2,6 +2,7 @@ id: d7_field_instance
label: Field instance configuration
migration_tags:
- Drupal 7
- Configuration
class: Drupal\migrate_drupal\Plugin\migrate\FieldMigration
field_plugin_method: processFieldInstance
source:
@@ -2,6 +2,7 @@ id: d7_field_instance_widget_settings
label: Field instance widget configuration
migration_tags:
- Drupal 7
- Configuration
class: Drupal\migrate_drupal\Plugin\migrate\FieldMigration
field_plugin_method: processFieldWidget
source:
@@ -2,6 +2,7 @@ id: d7_view_modes
label: View modes
migration_tags:
- Drupal 7
- Configuration
source:
plugin: d7_view_mode
process:
@@ -39,7 +39,7 @@ class ConfigImporterFieldPurger {
$field_storage->delete();
}
}
field_purge_batch($context['sandbox']['field']['purge_batch_size'], $field_storage->uuid());
field_purge_batch($context['sandbox']['field']['purge_batch_size'], $field_storage->getUniqueStorageIdentifier());
$context['sandbox']['field']['current_progress']++;
$fields_to_delete_count = count(static::getFieldStoragesToPurge($context['sandbox']['field']['extensions'], $config_importer->getUnprocessedConfiguration('delete')));
if ($fields_to_delete_count == 0) {
@@ -133,11 +133,11 @@ class ConfigImporterFieldPurger {
}
// Gather deleted fields from modules that are being uninstalled.
/** @var \Drupal\field\FieldStorageConfigInterface[] $field_storages */
$field_storages = entity_load_multiple_by_properties('field_storage_config', ['deleted' => TRUE, 'include_deleted' => TRUE]);
foreach ($field_storages as $field_storage) {
if (!in_array($field_storage->getTypeProvider(), $providers)) {
$storages_to_delete[$field_storage->id()] = $field_storage;
/** @var \Drupal\field\FieldStorageConfigInterface[] $deleted_storage_definitions */
$deleted_storage_definitions = \Drupal::service('entity_field.deleted_fields_repository')->getFieldStorageDefinitions();
foreach ($deleted_storage_definitions as $field_storage_definition) {
if ($field_storage_definition instanceof FieldStorageConfigInterface && !in_array($field_storage_definition->getTypeProvider(), $providers)) {
$storages_to_delete[$field_storage_definition->id()] = $field_storage_definition;
}
}
return $storages_to_delete;
+35 -13
View File
@@ -189,27 +189,26 @@ class FieldConfig extends FieldConfigBase implements FieldConfigInterface {
* {@inheritdoc}
*/
public static function preDelete(EntityStorageInterface $storage, array $fields) {
$state = \Drupal::state();
/** @var \Drupal\Core\Field\DeletedFieldsRepositoryInterface $deleted_fields_repository */
$deleted_fields_repository = \Drupal::service('entity_field.deleted_fields_repository');
$entity_type_manager = \Drupal::entityTypeManager();
parent::preDelete($storage, $fields);
// Keep the field definitions in the state storage so we can use them
// later during field_purge_batch().
$deleted_fields = $state->get('field.field.deleted') ?: [];
// Keep the field definitions in the deleted fields repository so we can use
// them later during field_purge_batch().
/** @var \Drupal\field\FieldConfigInterface $field */
foreach ($fields as $field) {
// Only mark a field for purging if there is data. Otherwise, just remove
// it.
$target_entity_storage = $entity_type_manager->getStorage($field->getTargetEntityTypeId());
if (!$field->deleted && $target_entity_storage instanceof FieldableEntityStorageInterface && $target_entity_storage->countFieldData($field->getFieldStorageDefinition(), TRUE)) {
$config = $field->toArray();
$config['deleted'] = TRUE;
$config['field_storage_uuid'] = $field->getFieldStorageDefinition()->uuid();
$deleted_fields[$field->uuid()] = $config;
$field = clone $field;
$field->deleted = TRUE;
$field->fieldStorage = NULL;
$deleted_fields_repository->addFieldDefinition($field);
}
}
$state->set('field.field.deleted', $deleted_fields);
}
/**
@@ -288,14 +287,30 @@ class FieldConfig extends FieldConfigBase implements FieldConfigInterface {
*/
public function getFieldStorageDefinition() {
if (!$this->fieldStorage) {
$fields = $this->entityManager()->getFieldStorageDefinitions($this->entity_type);
if (!isset($fields[$this->field_name])) {
$field_storage_definition = NULL;
$field_storage_definitions = $this->entityManager()->getFieldStorageDefinitions($this->entity_type);
if (isset($field_storage_definitions[$this->field_name])) {
$field_storage_definition = $field_storage_definitions[$this->field_name];
}
// If this field has been deleted, try to find its field storage
// definition in the deleted fields repository.
elseif ($this->deleted) {
$deleted_storage_definitions = \Drupal::service('entity_field.deleted_fields_repository')->getFieldStorageDefinitions();
foreach ($deleted_storage_definitions as $deleted_storage_definition) {
if ($deleted_storage_definition->getName() === $this->field_name) {
$field_storage_definition = $deleted_storage_definition;
}
}
}
if (!$field_storage_definition) {
throw new FieldException("Attempt to create a field {$this->field_name} that does not exist on entity type {$this->entity_type}.");
}
if (!$fields[$this->field_name] instanceof FieldStorageConfigInterface) {
if (!$field_storage_definition instanceof FieldStorageConfigInterface) {
throw new FieldException("Attempt to create a configurable field of non-configurable field storage {$this->field_name}.");
}
$this->fieldStorage = $fields[$this->field_name];
$this->fieldStorage = $field_storage_definition;
}
return $this->fieldStorage;
@@ -330,6 +345,13 @@ class FieldConfig extends FieldConfigBase implements FieldConfigInterface {
return FALSE;
}
/**
* {@inheritdoc}
*/
public function getUniqueIdentifier() {
return $this->uuid();
}
/**
* Loads a field config entity based on the entity type and field name.
*
@@ -398,7 +398,8 @@ class FieldStorageConfig extends ConfigEntityBase implements FieldStorageConfigI
* {@inheritdoc}
*/
public static function preDelete(EntityStorageInterface $storage, array $field_storages) {
$state = \Drupal::state();
/** @var \Drupal\Core\Field\DeletedFieldsRepositoryInterface $deleted_fields_repository */
$deleted_fields_repository = \Drupal::service('entity_field.deleted_fields_repository');
// Set the static flag so that we don't delete field storages whilst
// deleting fields.
@@ -407,23 +408,19 @@ class FieldStorageConfig extends ConfigEntityBase implements FieldStorageConfigI
// Delete or fix any configuration that is dependent, for example, fields.
parent::preDelete($storage, $field_storages);
// Keep the field definitions in the state storage so we can use them later
// during field_purge_batch().
$deleted_storages = $state->get('field.storage.deleted') ?: [];
// Keep the field storage definitions in the deleted fields repository so we
// can use them later during field_purge_batch().
/** @var \Drupal\field\FieldStorageConfigInterface $field_storage */
foreach ($field_storages as $field_storage) {
// Only mark a field for purging if there is data. Otherwise, just remove
// it.
$target_entity_storage = \Drupal::entityTypeManager()->getStorage($field_storage->getTargetEntityTypeId());
if (!$field_storage->deleted && $target_entity_storage instanceof FieldableEntityStorageInterface && $target_entity_storage->countFieldData($field_storage, TRUE)) {
$config = $field_storage->toArray();
$config['deleted'] = TRUE;
$config['bundles'] = $field_storage->getBundles();
$deleted_storages[$field_storage->uuid()] = $config;
$storage_definition = clone $field_storage;
$storage_definition->deleted = TRUE;
$deleted_fields_repository->addFieldStorageDefinition($storage_definition);
}
}
$state->set('field.storage.deleted', $deleted_storages);
}
/**
+21 -24
View File
@@ -5,16 +5,16 @@ namespace Drupal\field;
use Drupal\Core\Config\Config;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\DeletedFieldsRepositoryInterface;
use Drupal\Core\Field\FieldConfigStorageBase;
use Drupal\Core\Field\FieldTypePluginManagerInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Component\Uuid\UuidInterface;
use Drupal\Core\State\StateInterface;
/**
* Controller class for fields.
* Storage handler for field config.
*/
class FieldConfigStorage extends FieldConfigStorageBase {
@@ -25,13 +25,6 @@ class FieldConfigStorage extends FieldConfigStorageBase {
*/
protected $entityManager;
/**
* The state keyvalue collection.
*
* @var \Drupal\Core\State\StateInterface
*/
protected $state;
/**
* The field type plugin manager.
*
@@ -39,6 +32,13 @@ class FieldConfigStorage extends FieldConfigStorageBase {
*/
protected $fieldTypeManager;
/**
* The deleted fields repository.
*
* @var \Drupal\Core\Field\DeletedFieldsRepositoryInterface
*/
protected $deletedFieldsRepository;
/**
* Constructs a FieldConfigStorage object.
*
@@ -52,16 +52,16 @@ class FieldConfigStorage extends FieldConfigStorageBase {
* The language manager.
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The entity manager.
* @param \Drupal\Core\State\StateInterface $state
* The state key value store.
* @param \Drupal\Core\Field\FieldTypePluginManagerInterface $field_type_manager
* The field type plugin manager.
* @param \Drupal\Core\Field\DeletedFieldsRepositoryInterface $deleted_fields_repository
* The deleted fields repository.
*/
public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, UuidInterface $uuid_service, LanguageManagerInterface $language_manager, EntityManagerInterface $entity_manager, StateInterface $state, FieldTypePluginManagerInterface $field_type_manager) {
public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, UuidInterface $uuid_service, LanguageManagerInterface $language_manager, EntityManagerInterface $entity_manager, FieldTypePluginManagerInterface $field_type_manager, DeletedFieldsRepositoryInterface $deleted_fields_repository) {
parent::__construct($entity_type, $config_factory, $uuid_service, $language_manager);
$this->entityManager = $entity_manager;
$this->state = $state;
$this->fieldTypeManager = $field_type_manager;
$this->deletedFieldsRepository = $deleted_fields_repository;
}
/**
@@ -74,8 +74,8 @@ class FieldConfigStorage extends FieldConfigStorageBase {
$container->get('uuid'),
$container->get('language_manager'),
$container->get('entity.manager'),
$container->get('state'),
$container->get('plugin.manager.field.field_type')
$container->get('plugin.manager.field.field_type'),
$container->get('entity_field.deleted_fields_repository')
);
}
@@ -104,7 +104,7 @@ class FieldConfigStorage extends FieldConfigStorageBase {
// Get fields stored in configuration. If we are explicitly looking for
// deleted fields only, this can be skipped, because they will be
// retrieved from state below.
// retrieved from the deleted fields repository below.
if (empty($conditions['deleted'])) {
if (isset($conditions['entity_type']) && isset($conditions['bundle']) && isset($conditions['field_name'])) {
// Optimize for the most frequent case where we do have a specific ID.
@@ -117,16 +117,13 @@ class FieldConfigStorage extends FieldConfigStorageBase {
}
}
// Merge deleted fields (stored in state) if needed.
// Merge deleted fields from the deleted fields repository if needed.
if ($include_deleted || !empty($conditions['deleted'])) {
$deleted_fields = $this->state->get('field.field.deleted') ?: [];
$deleted_storages = $this->state->get('field.storage.deleted') ?: [];
foreach ($deleted_fields as $id => $config) {
// If the field storage itself is deleted, inject it directly in the field.
if (isset($deleted_storages[$config['field_storage_uuid']])) {
$config['field_storage'] = $this->entityManager->getStorage('field_storage_config')->create($deleted_storages[$config['field_storage_uuid']]);
$deleted_field_definitions = $this->deletedFieldsRepository->getFieldDefinitions();
foreach ($deleted_field_definitions as $id => $field_definition) {
if ($field_definition instanceof FieldConfigInterface) {
$fields[$id] = $field_definition;
}
$fields[$id] = $this->create($config);
}
}
@@ -34,14 +34,6 @@ interface FieldStorageConfigInterface extends ConfigEntityInterface, FieldStorag
*/
public function getBundles();
/**
* Returns whether the field is deleted or not.
*
* @return bool
* TRUE if the field is deleted.
*/
public function isDeleted();
/**
* Checks if the field storage can be deleted.
*
@@ -7,15 +7,15 @@ use Drupal\Core\Config\Entity\ConfigEntityStorage;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\DeletedFieldsRepositoryInterface;
use Drupal\Core\Field\FieldTypePluginManagerInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\State\StateInterface;
/**
* Controller class for "field storage" configuration entities.
* Storage handler for "field storage" configuration entities.
*/
class FieldStorageConfigStorage extends ConfigEntityStorage {
@@ -33,13 +33,6 @@ class FieldStorageConfigStorage extends ConfigEntityStorage {
*/
protected $entityManager;
/**
* The state keyvalue collection.
*
* @var \Drupal\Core\State\StateInterface
*/
protected $state;
/**
* The field type plugin manager.
*
@@ -47,6 +40,13 @@ class FieldStorageConfigStorage extends ConfigEntityStorage {
*/
protected $fieldTypeManager;
/**
* The deleted fields repository.
*
* @var \Drupal\Core\Field\DeletedFieldsRepositoryInterface
*/
protected $deletedFieldsRepository;
/**
* Constructs a FieldStorageConfigStorage object.
*
@@ -62,17 +62,17 @@ class FieldStorageConfigStorage extends ConfigEntityStorage {
* The entity manager.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler.
* @param \Drupal\Core\State\StateInterface $state
* The state key value store.
* @param \Drupal\Component\Plugin\PluginManagerInterface\FieldTypePluginManagerInterface $field_type_manager
* @param \Drupal\Core\Field\FieldTypePluginManagerInterface $field_type_manager
* The field type plugin manager.
* @param \Drupal\Core\Field\DeletedFieldsRepositoryInterface $deleted_fields_repository
* The deleted fields repository.
*/
public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, UuidInterface $uuid_service, LanguageManagerInterface $language_manager, EntityManagerInterface $entity_manager, ModuleHandlerInterface $module_handler, StateInterface $state, FieldTypePluginManagerInterface $field_type_manager) {
public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, UuidInterface $uuid_service, LanguageManagerInterface $language_manager, EntityManagerInterface $entity_manager, ModuleHandlerInterface $module_handler, FieldTypePluginManagerInterface $field_type_manager, DeletedFieldsRepositoryInterface $deleted_fields_repository) {
parent::__construct($entity_type, $config_factory, $uuid_service, $language_manager);
$this->entityManager = $entity_manager;
$this->moduleHandler = $module_handler;
$this->state = $state;
$this->fieldTypeManager = $field_type_manager;
$this->deletedFieldsRepository = $deleted_fields_repository;
}
/**
@@ -86,8 +86,8 @@ class FieldStorageConfigStorage extends ConfigEntityStorage {
$container->get('language_manager'),
$container->get('entity.manager'),
$container->get('module_handler'),
$container->get('state'),
$container->get('plugin.manager.field.field_type')
$container->get('plugin.manager.field.field_type'),
$container->get('entity_field.deleted_fields_repository')
);
}
@@ -104,7 +104,7 @@ class FieldStorageConfigStorage extends ConfigEntityStorage {
// Get field storages living in configuration. If we are explicitly looking
// for deleted storages only, this can be skipped, because they will be
// retrieved from state below.
// retrieved from the deleted fields repository below.
if (empty($conditions['deleted'])) {
if (isset($conditions['entity_type']) && isset($conditions['field_name'])) {
// Optimize for the most frequent case where we do have a specific ID.
@@ -117,11 +117,14 @@ class FieldStorageConfigStorage extends ConfigEntityStorage {
}
}
// Merge deleted field storages (living in state) if needed.
// Merge deleted field storage definitions from the deleted fields
// repository if needed.
if ($include_deleted || !empty($conditions['deleted'])) {
$deleted_storages = $this->state->get('field.storage.deleted') ?: [];
foreach ($deleted_storages as $id => $config) {
$storages[$id] = $this->create($config);
$deleted_storage_definitions = $this->deletedFieldsRepository->getFieldStorageDefinitions();
foreach ($deleted_storage_definitions as $id => $field_storage_definition) {
if ($field_storage_definition instanceof FieldStorageConfigInterface) {
$storages[$id] = $field_storage_definition;
}
}
}
@@ -0,0 +1,21 @@
<?php
namespace Drupal\field\Plugin\migrate\process;
@trigger_error('The field_type_defaults process plugin is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. Use d6_field_type_defaults or d7_field_type_defaults instead. See https://www.drupal.org/node/2944589.', E_USER_DEPRECATED);
use Drupal\field\Plugin\migrate\process\d6\FieldTypeDefaults as D6FieldTypeDefaults;
/**
* BC Layer.
*
* @MigrateProcessPlugin(
* id = "field_type_defaults"
* )
*
* @deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.x.
* Use d6_field_type_defaults or d7_field_type_defaults instead.
*
* @see https://www.drupal.org/node/2944589
*/
class FieldTypeDefaults extends D6FieldTypeDefaults {}
@@ -11,7 +11,7 @@ use Drupal\migrate\Row;
* Gives us a chance to set per field defaults.
*
* @MigrateProcessPlugin(
* id = "field_type_defaults"
* id = "d6_field_type_defaults"
* )
*/
class FieldTypeDefaults extends ProcessPluginBase {
@@ -0,0 +1,28 @@
<?php
namespace Drupal\field\Plugin\migrate\process\d7;
use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\Row;
/**
* Gives us a chance to set per field defaults.
*
* @MigrateProcessPlugin(
* id = "d7_field_type_defaults"
* )
*/
class FieldTypeDefaults extends ProcessPluginBase {
/**
* {@inheritdoc}
*/
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
if (is_array($value) && isset($value[1])) {
return $value[1];
}
return $value;
}
}
@@ -15,7 +15,7 @@ use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
*
* @MigrateSource(
* id = "d7_field",
* source_module = "field"
* source_module = "field_sql_storage"
* )
*/
class Field extends DrupalSqlBase {
@@ -94,6 +94,8 @@ class EntityReferenceAdminTest extends WebTestBase {
// The base handler settings should be displayed.
$entity_type_id = 'node';
// Check that the type label is correctly displayed.
$this->assertText('Content type');
$bundles = $this->container->get('entity_type.bundle.info')->getBundleInfo($entity_type_id);
foreach ($bundles as $bundle_name => $bundle_info) {
$this->assertFieldByName('settings[handler_settings][target_bundles][' . $bundle_name . ']');
@@ -114,7 +114,7 @@ class EntityReferenceFileUploadTest extends WebTestBase {
$this->drupalLogin($user1);
$test_file = current($this->drupalGetTestFiles('text'));
$edit['files[file_field_0]'] = drupal_realpath($test_file->uri);
$edit['files[file_field_0]'] = \Drupal::service('file_system')->realpath($test_file->uri);
$this->drupalPostForm('node/add/' . $this->referencingType, $edit, 'Upload');
$this->assertResponse(200);
$edit = [
+63
View File
@@ -113,6 +113,9 @@ class FormTest extends FieldTestBase {
// Check that hook_field_widget_form_alter() does not believe this is the
// default value form.
$this->assertNoText('From hook_field_widget_form_alter(): Default form is true.', 'Not default value form in hook_field_widget_form_alter().');
// Check that hook_field_widget_form_alter() does not believe this is the
// default value form.
$this->assertNoText('From hook_field_widget_multivalue_form_alter(): Default form is true.', 'Not default value form in hook_field_widget_form_alter().');
// Submit with invalid value (field-level validation).
$edit = [
@@ -634,4 +637,64 @@ class FormTest extends FieldTestBase {
$this->assertEscaped("<script>alert('a configurable field');</script>");
}
/**
* Tests hook_field_widget_multivalue_form_alter().
*/
public function testFieldFormMultipleWidgetAlter() {
$this->widgetAlterTest('hook_field_widget_multivalue_form_alter', 'test_field_widget_multiple');
}
/**
* Tests hook_field_widget_multivalue_form_alter() with single value elements.
*/
public function testFieldFormMultipleWidgetAlterSingleValues() {
$this->widgetAlterTest('hook_field_widget_multivalue_form_alter', 'test_field_widget_multiple_single_value');
}
/**
* Tests hook_field_widget_multivalue_WIDGET_TYPE_form_alter().
*/
public function testFieldFormMultipleWidgetTypeAlter() {
$this->widgetAlterTest('hook_field_widget_multivalue_WIDGET_TYPE_form_alter', 'test_field_widget_multiple');
}
/**
* Tests hook_field_widget_multivalue_WIDGET_TYPE_form_alter() with single value elements.
*/
public function testFieldFormMultipleWidgetTypeAlterSingleValues() {
$this->widgetAlterTest('hook_field_widget_multivalue_WIDGET_TYPE_form_alter', 'test_field_widget_multiple_single_value');
}
/**
* Tests widget alter hooks for a given hook name.
*/
protected function widgetAlterTest($hook, $widget) {
// Create a field with fixed cardinality, configure the form to use a
// "multiple" widget.
$field_storage = $this->fieldStorageMultiple;
$field_name = $field_storage['field_name'];
$this->field['field_name'] = $field_name;
FieldStorageConfig::create($field_storage)->save();
FieldConfig::create($this->field)->save();
// Set a flag in state so that the hook implementations will run.
\Drupal::state()->set("field_test.widget_alter_test", [
'hook' => $hook,
'field_name' => $field_name,
'widget' => $widget,
]);
entity_get_form_display($this->field['entity_type'], $this->field['bundle'], 'default')
->setComponent($field_name, [
'type' => $widget,
])
->save();
$this->drupalGet('entity_test/add');
$this->assertUniqueText("From $hook(): prefix on $field_name parent element.");
if ($widget === 'test_field_widget_multiple_single_value') {
$suffix_text = "From $hook(): suffix on $field_name child element.";
$this->assertEqual($field_storage['cardinality'], substr_count($this->getTextContent(), $suffix_text), "'$suffix_text' was found {$field_storage['cardinality']} times using widget $widget");
}
}
}
@@ -32,7 +32,7 @@ class StringFieldTest extends WebTestBase {
protected function setUp() {
parent::setUp();
$this->webUser = $this->drupalCreateUser(['view test entity', 'administer entity_test content']);
$this->webUser = $this->drupalCreateUser(['view test entity', 'administer entity_test content', 'access content']);
$this->drupalLogin($this->webUser);
}
@@ -42,8 +42,8 @@ abstract class FieldTestBase extends ViewTestBase {
*/
public $fields;
protected function setUp() {
parent::setUp();
protected function setUp($import_test_views = TRUE) {
parent::setUp($import_test_views);
// Ensure the page node type exists.
NodeType::create([
@@ -38,8 +38,8 @@ class FieldUITest extends FieldTestBase {
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
protected function setUp($import_test_views = TRUE) {
parent::setUp($import_test_views);
$this->account = $this->drupalCreateUser(['administer views']);
$this->drupalLogin($this->account);
@@ -41,8 +41,8 @@ class HandlerFieldFieldTest extends FieldTestBase {
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
protected function setUp($import_test_views = TRUE) {
parent::setUp($import_test_views);
// Setup basic fields.
$this->setUpFieldStorages(3);
@@ -86,7 +86,7 @@ class reEnableModuleFieldTest extends WebTestBase {
$this->assertRaw('<a href="tel:123456789">');
// Test that the module can't be uninstalled from the UI while there is data
// for it's fields.
// for its fields.
$admin_user = $this->drupalCreateUser(['access administration pages', 'administer modules']);
$this->drupalLogin($admin_user);
$this->drupalGet('admin/modules/uninstall');
@@ -0,0 +1,203 @@
<?php
// @codingStandardsIgnoreFile
/**
* @file
* Contains SQL necessary to add a deleted field to the node entity type.
*/
use Drupal\Core\Database\Database;
$connection = Database::getConnection();
// Add the field schema data and the deleted field definitions.
$connection->insert('key_value')
->fields([
'collection',
'name',
'value',
])
->values([
'collection' => 'entity.storage_schema.sql',
'name' => 'node.field_schema_data.field_test',
'value' => 'a:2:{s:16:"node__field_test";a:4:{s:11:"description";s:39:"Data storage for node field field_test.";s:6:"fields";a:7:{s:6:"bundle";a:5:{s:4:"type";s:13:"varchar_ascii";s:6:"length";i:128;s:8:"not null";b:1;s:7:"default";s:0:"";s:11:"description";s:88:"The field instance bundle to which this row belongs, used when deleting a field instance";}s:7:"deleted";a:5:{s:4:"type";s:3:"int";s:4:"size";s:4:"tiny";s:8:"not null";b:1;s:7:"default";i:0;s:11:"description";s:60:"A boolean indicating whether this data item has been deleted";}s:9:"entity_id";a:4:{s:4:"type";s:3:"int";s:8:"unsigned";b:1;s:8:"not null";b:1;s:11:"description";s:38:"The entity id this data is attached to";}s:11:"revision_id";a:4:{s:4:"type";s:3:"int";s:8:"unsigned";b:1;s:8:"not null";b:1;s:11:"description";s:47:"The entity revision id this data is attached to";}s:8:"langcode";a:5:{s:4:"type";s:13:"varchar_ascii";s:6:"length";i:32;s:8:"not null";b:1;s:7:"default";s:0:"";s:11:"description";s:37:"The language code for this data item.";}s:5:"delta";a:4:{s:4:"type";s:3:"int";s:8:"unsigned";b:1;s:8:"not null";b:1;s:11:"description";s:67:"The sequence number for this data item, used for multi-value fields";}s:16:"field_test_value";a:3:{s:4:"type";s:7:"varchar";s:6:"length";i:254;s:8:"not null";b:1;}}s:11:"primary key";a:4:{i:0;s:9:"entity_id";i:1;s:7:"deleted";i:2;s:5:"delta";i:3;s:8:"langcode";}s:7:"indexes";a:2:{s:6:"bundle";a:1:{i:0;s:6:"bundle";}s:11:"revision_id";a:1:{i:0;s:11:"revision_id";}}}s:25:"node_revision__field_test";a:4:{s:11:"description";s:51:"Revision archive storage for node field field_test.";s:6:"fields";a:7:{s:6:"bundle";a:5:{s:4:"type";s:13:"varchar_ascii";s:6:"length";i:128;s:8:"not null";b:1;s:7:"default";s:0:"";s:11:"description";s:88:"The field instance bundle to which this row belongs, used when deleting a field instance";}s:7:"deleted";a:5:{s:4:"type";s:3:"int";s:4:"size";s:4:"tiny";s:8:"not null";b:1;s:7:"default";i:0;s:11:"description";s:60:"A boolean indicating whether this data item has been deleted";}s:9:"entity_id";a:4:{s:4:"type";s:3:"int";s:8:"unsigned";b:1;s:8:"not null";b:1;s:11:"description";s:38:"The entity id this data is attached to";}s:11:"revision_id";a:4:{s:4:"type";s:3:"int";s:8:"unsigned";b:1;s:8:"not null";b:1;s:11:"description";s:47:"The entity revision id this data is attached to";}s:8:"langcode";a:5:{s:4:"type";s:13:"varchar_ascii";s:6:"length";i:32;s:8:"not null";b:1;s:7:"default";s:0:"";s:11:"description";s:37:"The language code for this data item.";}s:5:"delta";a:4:{s:4:"type";s:3:"int";s:8:"unsigned";b:1;s:8:"not null";b:1;s:11:"description";s:67:"The sequence number for this data item, used for multi-value fields";}s:16:"field_test_value";a:3:{s:4:"type";s:7:"varchar";s:6:"length";i:254;s:8:"not null";b:1;}}s:11:"primary key";a:5:{i:0;s:9:"entity_id";i:1;s:11:"revision_id";i:2;s:7:"deleted";i:3;s:5:"delta";i:4;s:8:"langcode";}s:7:"indexes";a:2:{s:6:"bundle";a:1:{i:0;s:6:"bundle";}s:11:"revision_id";a:1:{i:0;s:11:"revision_id";}}}}',
])
->values([
'collection' => 'state',
'name' => 'field.field.deleted',
'value' => 'a:1:{s:36:"5d0d9870-560b-46c4-b838-0dcded0502dd";a:18:{s:4:"uuid";s:36:"5d0d9870-560b-46c4-b838-0dcded0502dd";s:8:"langcode";s:2:"en";s:6:"status";b:1;s:12:"dependencies";a:1:{s:6:"config";a:2:{i:0;s:29:"field.storage.node.field_test";i:1;s:17:"node.type.article";}}s:2:"id";s:23:"node.article.field_test";s:10:"field_name";s:10:"field_test";s:11:"entity_type";s:4:"node";s:6:"bundle";s:7:"article";s:5:"label";s:4:"Test";s:11:"description";s:0:"";s:8:"required";b:0;s:12:"translatable";b:0;s:13:"default_value";a:0:{}s:22:"default_value_callback";s:0:"";s:8:"settings";a:0:{}s:10:"field_type";s:5:"email";s:7:"deleted";b:1;s:18:"field_storage_uuid";s:36:"ce93d7c2-1da7-4a2c-9e6d-b4925e3b129f";}}',
])
->values([
'collection' => 'state',
'name' => 'field.storage.deleted',
'value' => 'a:1:{s:36:"ce93d7c2-1da7-4a2c-9e6d-b4925e3b129f";a:18:{s:4:"uuid";s:36:"ce93d7c2-1da7-4a2c-9e6d-b4925e3b129f";s:8:"langcode";s:2:"en";s:6:"status";b:1;s:12:"dependencies";a:1:{s:6:"module";a:1:{i:0;s:4:"node";}}s:2:"id";s:15:"node.field_test";s:10:"field_name";s:10:"field_test";s:11:"entity_type";s:4:"node";s:4:"type";s:5:"email";s:8:"settings";a:0:{}s:6:"module";s:4:"core";s:6:"locked";b:0;s:11:"cardinality";i:1;s:12:"translatable";b:1;s:7:"indexes";a:0:{}s:22:"persist_with_no_fields";b:0;s:14:"custom_storage";b:0;s:7:"deleted";b:1;s:7:"bundles";a:0:{}}}',
])
->execute();
// Create and populate the deleted field tables.
// @see \Drupal\Core\Entity\Sql\DefaultTableMapping::getDedicatedDataTableName()
$deleted_field_data_table_name = "field_deleted_data_" . substr(hash('sha256', 'ce93d7c2-1da7-4a2c-9e6d-b4925e3b129f'), 0, 10);
$connection->schema()->createTable($deleted_field_data_table_name, array(
'fields' => array(
'bundle' => array(
'type' => 'varchar_ascii',
'not null' => TRUE,
'length' => '128',
'default' => '',
),
'deleted' => array(
'type' => 'int',
'not null' => TRUE,
'size' => 'tiny',
'default' => '0',
),
'entity_id' => array(
'type' => 'int',
'not null' => TRUE,
'size' => 'normal',
'unsigned' => TRUE,
),
'revision_id' => array(
'type' => 'int',
'not null' => TRUE,
'size' => 'normal',
'unsigned' => TRUE,
),
'langcode' => array(
'type' => 'varchar_ascii',
'not null' => TRUE,
'length' => '32',
'default' => '',
),
'delta' => array(
'type' => 'int',
'not null' => TRUE,
'size' => 'normal',
'unsigned' => TRUE,
),
'field_test_value' => array(
'type' => 'varchar',
'not null' => TRUE,
'length' => '254',
),
),
'primary key' => array(
'entity_id',
'deleted',
'delta',
'langcode',
),
'indexes' => array(
'bundle' => array(
'bundle',
),
'revision_id' => array(
'revision_id',
),
),
));
$connection->insert($deleted_field_data_table_name)
->fields(array(
'bundle',
'deleted',
'entity_id',
'revision_id',
'langcode',
'delta',
'field_test_value',
))
->values(array(
'bundle' => 'article',
'deleted' => '1',
'entity_id' => '1',
'revision_id' => '1',
'langcode' => 'en',
'delta' => '0',
'field_test_value' => 'test@test.com',
))
->execute();
// @see \Drupal\Core\Entity\Sql\DefaultTableMapping::getDedicatedDataTableName()
$deleted_field_revision_table_name = "field_deleted_revision_" . substr(hash('sha256', 'ce93d7c2-1da7-4a2c-9e6d-b4925e3b129f'), 0, 10);
$connection->schema()->createTable($deleted_field_revision_table_name, array(
'fields' => array(
'bundle' => array(
'type' => 'varchar_ascii',
'not null' => TRUE,
'length' => '128',
'default' => '',
),
'deleted' => array(
'type' => 'int',
'not null' => TRUE,
'size' => 'tiny',
'default' => '0',
),
'entity_id' => array(
'type' => 'int',
'not null' => TRUE,
'size' => 'normal',
'unsigned' => TRUE,
),
'revision_id' => array(
'type' => 'int',
'not null' => TRUE,
'size' => 'normal',
'unsigned' => TRUE,
),
'langcode' => array(
'type' => 'varchar_ascii',
'not null' => TRUE,
'length' => '32',
'default' => '',
),
'delta' => array(
'type' => 'int',
'not null' => TRUE,
'size' => 'normal',
'unsigned' => TRUE,
),
'field_test_value' => array(
'type' => 'varchar',
'not null' => TRUE,
'length' => '254',
),
),
'primary key' => array(
'entity_id',
'revision_id',
'deleted',
'delta',
'langcode',
),
'indexes' => array(
'bundle' => array(
'bundle',
),
'revision_id' => array(
'revision_id',
),
),
));
$connection->insert($deleted_field_revision_table_name)
->fields(array(
'bundle',
'deleted',
'entity_id',
'revision_id',
'langcode',
'delta',
'field_test_value',
))
->values(array(
'bundle' => 'article',
'deleted' => '1',
'entity_id' => '1',
'revision_id' => '1',
'langcode' => 'en',
'delta' => '0',
'field_test_value' => 'test@test.com',
))
->execute();
@@ -7,8 +7,8 @@ package: Testing
dependencies:
- text
# Information added by Drupal.org packaging script on 2018-01-03
version: '8.4.4'
# Information added by Drupal.org packaging script on 2018-03-07
version: '8.5.0'
core: '8.x'
project: 'drupal'
datestamp: 1515021228
datestamp: 1520457825
@@ -55,6 +55,14 @@ field.widget.settings.test_field_widget_multiple:
type: string
label: 'Test setting'
field.widget.settings.test_field_widget_multiple_single_value:
type: mapping
label: 'Test multiple field widget settings: single values'
mapping:
test_widget_setting_multiple:
type: string
label: 'Test setting'
field.widget.third_party.color:
type: mapping
label: 'Field test entity display color module third party settings'
@@ -19,6 +19,13 @@ use Drupal\field\FieldStorageConfigInterface;
function field_test_field_widget_info_alter(&$info) {
$info['test_field_widget_multiple']['field_types'][] = 'test_field';
$info['test_field_widget_multiple']['field_types'][] = 'test_field_with_preconfigured_options';
// Add extra widget when needed for tests.
// @see \Drupal\field\Tests\FormTest::widgetAlterTest().
if ($alter_info = \Drupal::state()->get("field_test.widget_alter_test")) {
if ($alter_info['widget'] === 'test_field_widget_multiple_single_value') {
$info['test_field_widget_multiple_single_value']['field_types'][] = 'test_field';
}
}
}
/**
@@ -7,8 +7,8 @@ package: Testing
dependencies:
- entity_test
# Information added by Drupal.org packaging script on 2018-01-03
version: '8.4.4'
# Information added by Drupal.org packaging script on 2018-03-07
version: '8.5.0'
core: '8.x'
project: 'drupal'
datestamp: 1515021228
datestamp: 1520457825
@@ -15,6 +15,7 @@
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Drupal\field\FieldStorageConfigInterface;
require_once __DIR__ . '/field_test.entity.inc';
@@ -100,16 +101,6 @@ function field_test_entity_display_build_alter(&$output, $context) {
* Implements hook_field_widget_form_alter().
*/
function field_test_field_widget_form_alter(&$element, FormStateInterface $form_state, $context) {
$field_definition = $context['items']->getFieldDefinition();
switch ($field_definition->getName()) {
case 'alter_test_text':
drupal_set_message('Field size: ' . $context['widget']->getSetting('size'));
break;
case 'alter_test_options':
drupal_set_message('Widget type: ' . $context['widget']->getPluginId());
break;
}
// Set a message if this is for the form displayed to set default value for
// the field.
if ($context['default']) {
@@ -117,6 +108,50 @@ function field_test_field_widget_form_alter(&$element, FormStateInterface $form_
}
}
/**
* Implements hook_field_widget_multivalue_form_alter().
*/
function field_test_field_widget_multivalue_form_alter(array &$elements, FormStateInterface $form_state, array $context) {
_field_test_alter_widget("hook_field_widget_multivalue_form_alter", $elements, $form_state, $context);
}
/**
* Implements hook_field_widget_multivalue_WIDGET_TYPE_form_alter().
*/
function field_test_field_widget_multivalue_test_field_widget_multiple_form_alter(array &$elements, FormStateInterface $form_state, array $context) {
_field_test_alter_widget("hook_field_widget_multivalue_WIDGET_TYPE_form_alter", $elements, $form_state, $context);
}
/**
* Implements hook_field_widget_multivalue_WIDGET_TYPE_form_alter().
*/
function field_test_field_widget_multivalue_test_field_widget_multiple_single_value_form_alter(array &$elements, FormStateInterface $form_state, array $context) {
_field_test_alter_widget("hook_field_widget_multivalue_WIDGET_TYPE_form_alter", $elements, $form_state, $context);
}
/**
* Sets up alterations for widget alter tests.
*
* @see \Drupal\field\Tests\FormTest::widgetAlterTest()
*/
function _field_test_alter_widget($hook, array &$elements, FormStateInterface $form_state, array $context) {
// Set a message if this is for the form displayed to set default value for
// the field.
if ($context['default']) {
drupal_set_message("From $hook(): Default form is true.");
}
$alter_info = \Drupal::state()->get("field_test.widget_alter_test");
$name = $context['items']->getFieldDefinition()->getName();
if (!empty($alter_info) && $hook === $alter_info['hook'] && $name === $alter_info['field_name']) {
$elements['#prefix'] = "From $hook(): prefix on $name parent element.";
foreach (Element::children($elements) as $delta => $element) {
$elements[$delta]['#suffix'] = "From $hook(): suffix on $name child element.";
}
}
}
/**
* Implements hook_query_TAG_alter() for tag 'efq_table_prefixing_test'.
*
@@ -171,3 +206,14 @@ function field_test_entity_bundle_field_info_alter(&$fields, EntityTypeInterface
]);
}
}
/**
* Implements hook_field_ui_preconfigured_options_alter().
*/
function field_test_field_ui_preconfigured_options_alter(array &$options, $field_type) {
if ($field_type === 'test_field_with_preconfigured_options') {
$options['custom_options']['entity_view_display']['settings'] = [
'test_formatter_setting_multiple' => 'altered dummy test string',
];
}
}
@@ -10,6 +10,8 @@ use Drupal\Core\Entity\Entity\EntityFormDisplay;
/**
* Provides a form for field_test routes.
*
* @internal
*/
class NestedEntityTestForm extends FormBase {
@@ -0,0 +1,22 @@
<?php
namespace Drupal\field_test\Plugin\Field\FieldWidget;
/**
* Plugin implementation of the 'test_field_widget_multiple' widget.
*
* The 'field_types' entry is left empty, and is populated through
* hook_field_widget_info_alter().
*
* @see field_test_field_widget_info_alter()
*
* @FieldWidget(
* id = "test_field_widget_multiple_single_value",
* label = @Translation("Test widget - multiple - single value"),
* multiple_values = FALSE,
* weight = 10
* )
*/
class TestFieldWidgetMultipleSingleValues extends TestFieldWidgetMultiple {
}
@@ -7,8 +7,8 @@ package: Testing
dependencies:
- field
# Information added by Drupal.org packaging script on 2018-01-03
version: '8.4.4'
# Information added by Drupal.org packaging script on 2018-03-07
version: '8.5.0'
core: '8.x'
project: 'drupal'
datestamp: 1515021228
datestamp: 1520457825
@@ -5,8 +5,8 @@ description: 'Support module for the Field API configuration tests.'
package: Testing
# version: VERSION
# Information added by Drupal.org packaging script on 2018-01-03
version: '8.4.4'
# Information added by Drupal.org packaging script on 2018-03-07
version: '8.5.0'
core: '8.x'
project: 'drupal'
datestamp: 1515021228
datestamp: 1520457825
@@ -7,8 +7,8 @@ package: Testing
dependencies:
- views
# Information added by Drupal.org packaging script on 2018-01-03
version: '8.4.4'
# Information added by Drupal.org packaging script on 2018-03-07
version: '8.5.0'
core: '8.x'
project: 'drupal'
datestamp: 1515021228
datestamp: 1520457825
@@ -8,8 +8,8 @@ dependencies:
- entity_test
- field_test
# Information added by Drupal.org packaging script on 2018-01-03
version: '8.4.4'
# Information added by Drupal.org packaging script on 2018-03-07
version: '8.5.0'
core: '8.x'
project: 'drupal'
datestamp: 1515021228
datestamp: 1520457825
@@ -0,0 +1,19 @@
langcode: en
status: true
dependencies:
config:
- field.storage.entity_test.timestamp
id: entity_test.entity_test.timestamp
field_name: timestamp
entity_type: entity_test
bundle: entity_test
label: 'Time stamp'
description: ''
required: false
translatable: false
default_value:
-
value: 1514847537
default_value_callback: ''
settings: { }
field_type: timestamp
@@ -0,0 +1,17 @@
langcode: en
status: true
dependencies:
module:
- entity_test
id: node.timestamp
field_name: timestamp
entity_type: entity_test
type: timestamp
settings: { }
module: core
locked: false
cardinality: 1
translatable: true
indexes: { }
persist_with_no_fields: false
custom_storage: false
@@ -0,0 +1,15 @@
name: 'Field Timestamp Test'
type: module
description: 'Support module for the Timestamp field item test.'
# core: 8.x
package: Testing
# version: VERSION
dependencies:
- entity_test
- field
# Information added by Drupal.org packaging script on 2018-03-07
version: '8.5.0'
core: '8.x'
project: 'drupal'
datestamp: 1520457825
@@ -1,19 +1,19 @@
<?php
namespace Drupal\field\Tests\Boolean;
namespace Drupal\Tests\field\Functional\Boolean;
use Drupal\Component\Utility\Unicode;
use Drupal\entity_test\Entity\EntityTest;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\field\Entity\FieldConfig;
use Drupal\simpletest\WebTestBase;
use Drupal\Tests\BrowserTestBase;
/**
* Tests boolean field functionality.
*
* @group field
*/
class BooleanFieldTest extends WebTestBase {
class BooleanFieldTest extends BrowserTestBase {
/**
* Modules to enable.
@@ -108,15 +108,13 @@ class BooleanFieldTest extends WebTestBase {
"{$field_name}[value]" => 1,
];
$this->drupalPostForm(NULL, $edit, t('Save'));
preg_match('|entity_test/manage/(\d+)|', $this->url, $match);
preg_match('|entity_test/manage/(\d+)|', $this->getUrl(), $match);
$id = $match[1];
$this->assertText(t('entity_test @id has been created.', ['@id' => $id]));
// Verify that boolean value is displayed.
$entity = EntityTest::load($id);
$display = entity_get_display($entity->getEntityTypeId(), $entity->bundle(), 'full');
$content = $display->build($entity);
$this->setRawContent(\Drupal::service('renderer')->renderRoot($content));
$this->drupalGet($entity->toUrl());
$this->assertRaw('<div class="field__item">' . $on . '</div>');
// Test with "On" label option.
@@ -150,16 +148,16 @@ class BooleanFieldTest extends WebTestBase {
$this->drupalGet($fieldEditUrl);
// Click on the widget settings button to open the widget settings form.
$this->drupalPostAjaxForm(NULL, [], $field_name . "_settings_edit");
$this->drupalPostForm(NULL, [], $field_name . "_settings_edit");
$this->assertText(
'Use field label instead of the "On label" as label',
'Use field label instead of the "On" label as the label.',
t('Display setting checkbox available.')
);
// Enable setting.
$edit = ['fields[' . $field_name . '][settings_edit_form][settings][display_label]' => 1];
$this->drupalPostAjaxForm(NULL, $edit, $field_name . "_plugin_settings_update");
$this->drupalPostForm(NULL, $edit, $field_name . "_plugin_settings_update");
$this->drupalPostForm(NULL, NULL, 'Save');
// Go again to the form display page and check if the setting
@@ -167,16 +165,12 @@ class BooleanFieldTest extends WebTestBase {
$this->drupalGet($fieldEditUrl);
$this->assertText('Use field label: Yes', 'Checking the display settings checkbox updated the value.');
$this->drupalPostAjaxForm(NULL, [], $field_name . "_settings_edit");
$this->drupalPostForm(NULL, [], $field_name . "_settings_edit");
$this->assertText(
'Use field label instead of the "On label" as label',
'Use field label instead of the "On" label as the label.',
t('Display setting checkbox is available')
);
$this->assertFieldByXPath(
'*//input[starts-with(@id, "edit-fields-' . $field_name . '-settings-edit-form-settings-display-label") and @value="1"]',
TRUE,
t('Display label changes label of the checkbox')
);
$this->getSession()->getPage()->hasCheckedField('fields[' . $field_name . '][settings_edit_form][settings][display_label]');
// Test the boolean field settings.
$this->drupalGet('entity_test/structure/entity_test/fields/entity_test.entity_test.' . $field_name);
@@ -230,7 +224,7 @@ class BooleanFieldTest extends WebTestBase {
// Should be posted OK.
$this->drupalPostForm(NULL, [], t('Save'));
preg_match('|entity_test/manage/(\d+)|', $this->url, $match);
preg_match('|entity_test/manage/(\d+)|', $this->getUrl(), $match);
$id = $match[1];
$this->assertText(t('entity_test @id has been created.', ['@id' => $id]));
@@ -241,7 +235,7 @@ class BooleanFieldTest extends WebTestBase {
$this->assertNoFieldByName("{$field_name}[value]");
// Should still be able to post the form.
$this->drupalPostForm(NULL, [], t('Save'));
preg_match('|entity_test/manage/(\d+)|', $this->url, $match);
preg_match('|entity_test/manage/(\d+)|', $this->getUrl(), $match);
$id = $match[1];
$this->assertText(t('entity_test @id has been created.', ['@id' => $id]));
}
@@ -3,9 +3,12 @@
namespace Drupal\Tests\field\Functional\Update;
use Drupal\Core\Config\Config;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
use Drupal\node\Entity\Node;
use Drupal\Tests\Traits\Core\CronRunTrait;
/**
* Tests that field settings are properly updated during database updates.
@@ -14,6 +17,8 @@ use Drupal\node\Entity\Node;
*/
class FieldUpdateTest extends UpdatePathTestBase {
use CronRunTrait;
/**
* The config factory service.
*
@@ -21,12 +26,45 @@ class FieldUpdateTest extends UpdatePathTestBase {
*/
protected $configFactory;
/**
* The database connection.
*
* @var \Drupal\Core\Database\Connection
*/
protected $database;
/**
* The key-value collection for tracking installed storage schema.
*
* @var \Drupal\Core\KeyValueStore\KeyValueStoreInterface
*/
protected $installedStorageSchema;
/**
* The state service.
*
* @var \Drupal\Core\State\StateInterface
*/
protected $state;
/**
* The deleted fields repository.
*
* @var \Drupal\Core\Field\DeletedFieldsRepositoryInterface
*/
protected $deletedFieldsRepository;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->configFactory = $this->container->get('config.factory');
$this->database = $this->container->get('database');
$this->installedStorageSchema = $this->container->get('keyvalue')->get('entity.storage_schema.sql');
$this->state = $this->container->get('state');
$this->deletedFieldsRepository = $this->container->get('entity_field.deleted_fields_repository');
}
/**
@@ -37,6 +75,7 @@ class FieldUpdateTest extends UpdatePathTestBase {
__DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
__DIR__ . '/../../../fixtures/update/drupal-8.views_entity_reference_plugins-2429191.php',
__DIR__ . '/../../../fixtures/update/drupal-8.remove_handler_submit_setting-2715589.php',
__DIR__ . '/../../../fixtures/update/drupal-8.update_deleted_field_definitions-2931436.php',
];
}
@@ -127,6 +166,76 @@ class FieldUpdateTest extends UpdatePathTestBase {
$this->assertEqual($handler_settings['auto_create_bundle'], 'tags');
}
/**
* Tests field_update_8500().
*
* @see field_update_8500()
*/
public function testFieldUpdate8500() {
$field_name = 'field_test';
$field_uuid = '5d0d9870-560b-46c4-b838-0dcded0502dd';
$field_storage_uuid = 'ce93d7c2-1da7-4a2c-9e6d-b4925e3b129f';
// Check that we have pre-existing entries for 'field.field.deleted' and
// 'field.storage.deleted'.
$deleted_fields = $this->state->get('field.field.deleted');
$this->assertCount(1, $deleted_fields);
$this->assertArrayHasKey($field_uuid, $deleted_fields);
$deleted_field_storages = $this->state->get('field.storage.deleted');
$this->assertCount(1, $deleted_field_storages);
$this->assertArrayHasKey($field_storage_uuid, $deleted_field_storages);
// Ensure that cron does not run automatically after running the updates.
$this->state->set('system.cron_last', REQUEST_TIME + 100);
// Run updates.
$this->runUpdates();
// Now that we can use the API, check that the "delete fields" state entries
// have been converted to proper field definition objects.
$deleted_fields = $this->deletedFieldsRepository->getFieldDefinitions();
$this->assertCount(1, $deleted_fields);
$this->assertArrayHasKey($field_uuid, $deleted_fields);
$this->assertTrue($deleted_fields[$field_uuid] instanceof FieldDefinitionInterface);
$this->assertEquals($field_name, $deleted_fields[$field_uuid]->getName());
$deleted_field_storages = $this->deletedFieldsRepository->getFieldStorageDefinitions();
$this->assertCount(1, $deleted_field_storages);
$this->assertArrayHasKey($field_storage_uuid, $deleted_field_storages);
$this->assertTrue($deleted_field_storages[$field_storage_uuid] instanceof FieldStorageDefinitionInterface);
$this->assertEquals($field_name, $deleted_field_storages[$field_storage_uuid]->getName());
// Check that the installed storage schema still exists.
$this->assertNotNull($this->installedStorageSchema->get("node.field_schema_data.$field_name"));
// Check that the deleted field tables exist.
/** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */
$table_mapping = \Drupal::entityTypeManager()->getStorage('node')->getTableMapping();
$deleted_field_data_table_name = $table_mapping->getDedicatedDataTableName($deleted_field_storages[$field_storage_uuid], TRUE);
$this->assertTrue($this->database->schema()->tableExists($deleted_field_data_table_name));
$deleted_field_revision_table_name = $table_mapping->getDedicatedRevisionTableName($deleted_field_storages[$field_storage_uuid], TRUE);
$this->assertTrue($this->database->schema()->tableExists($deleted_field_revision_table_name));
// Run cron and repeat the checks above.
$this->cronRun();
$deleted_fields = $this->deletedFieldsRepository->getFieldDefinitions();
$this->assertCount(0, $deleted_fields);
$deleted_field_storages = $this->deletedFieldsRepository->getFieldStorageDefinitions();
$this->assertCount(0, $deleted_field_storages);
// Check that the installed storage schema has been deleted.
$this->assertNull($this->installedStorageSchema->get("node.field_schema_data.$field_name"));
// Check that the deleted field tables have been deleted.
$this->assertFalse($this->database->schema()->tableExists($deleted_field_data_table_name));
$this->assertFalse($this->database->schema()->tableExists($deleted_field_revision_table_name));
}
/**
* Asserts that a config depends on 'entity_reference' or not
*
@@ -16,6 +16,7 @@ use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\node\NodeInterface;
use Drupal\taxonomy\TermInterface;
use Drupal\Tests\field\Kernel\FieldKernelTestBase;
use Drupal\file\Entity\File;
use Drupal\node\Entity\Node;
@@ -193,6 +194,24 @@ class EntityReferenceItemTest extends FieldKernelTestBase {
$entity = EntityTest::create(['user_id' => ['target_id' => (int) $user->id(), 'entity' => $user]]);
}
/**
* Tests the ::generateSampleValue() method.
*/
public function testGenerateSampleValue() {
$entity = EntityTest::create();
// Test while a term exists.
$entity->field_test_taxonomy_term->generateSampleItems();
$this->assertInstanceOf(TermInterface::class, $entity->field_test_taxonomy_term->entity);
$this->entityValidateAndSave($entity);
// Delete the term and test again.
$this->term->delete();
$entity->field_test_taxonomy_term->generateSampleItems();
$this->assertInstanceOf(TermInterface::class, $entity->field_test_taxonomy_term->entity);
$this->entityValidateAndSave($entity);
}
/**
* Tests referencing content entities with string IDs.
*/
@@ -67,7 +67,7 @@ class EntityReferenceRelationshipTest extends ViewsKernelTestBase {
// Create reference from entity_test_mul to entity_test.
$this->createEntityReferenceField('entity_test_mul', 'entity_test_mul', 'field_data_test', 'field_data_test', 'entity_test');
// Create another field for testing with a long name. So it's storage name
// Create another field for testing with a long name. So its storage name
// will become hashed. Use entity_test_mul_changed, so the resulting field
// tables created will be greater than 48 chars long.
// @see \Drupal\Core\Entity\Sql\DefaultTableMapping::generateFieldTableName()
@@ -129,11 +129,14 @@ class MigrateFieldFormatterSettingsTest extends MigrateDrupal6TestBase {
// Test the file field formatter settings.
$expected['weight'] = 8;
$expected['type'] = 'file_default';
$expected['settings'] = [];
$expected['settings'] = [
'use_description_as_link_text' => TRUE
];
$component = $display->getComponent('field_test_filefield');
$this->assertIdentical($expected, $component);
$display = EntityViewDisplay::load('node.story.default');
$expected['type'] = 'file_url_plain';
$expected['settings'] = [];
$component = $display->getComponent('field_test_filefield');
$this->assertIdentical($expected, $component);
@@ -21,9 +21,9 @@ class FieldConfigAccessControlHandlerTest extends FieldStorageConfigAccessContro
parent::setUp();
$this->entity = new FieldConfig([
'field_name' => $this->fieldStorage->getName(),
'field_name' => $this->entity->getName(),
'entity_type' => 'node',
'fieldStorage' => $this->fieldStorage,
'fieldStorage' => $this->entity,
'bundle' => 'test_bundle',
'field_type' => 'test_field',
], 'node');
@@ -10,6 +10,9 @@ namespace Drupal\Tests\field\Unit;
use Drupal\Core\Entity\EntityType;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityManager;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\Tests\UnitTestCase;
@@ -33,6 +36,20 @@ class FieldConfigEntityUnitTest extends UnitTestCase {
*/
protected $entityManager;
/**
* The entity type manager used for testing.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $entityTypeManager;
/**
* The entity field manager used for testing.
*
* @var \Drupal\Core\Entity\EntityFieldManagerInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $entityFieldManager;
/**
* The ID of the type of the entity under test.
*
@@ -75,7 +92,9 @@ class FieldConfigEntityUnitTest extends UnitTestCase {
$this->entityTypeId = $this->randomMachineName();
$this->entityType = $this->getMock('\Drupal\Core\Config\Entity\ConfigEntityTypeInterface');
$this->entityManager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface');
$this->entityManager = new EntityManager();
$this->entityTypeManager = $this->getMock(EntityTypeManagerInterface::class);
$this->entityFieldManager = $this->getMock(EntityFieldManagerInterface::class);
$this->uuid = $this->getMock('\Drupal\Component\Uuid\UuidInterface');
@@ -85,9 +104,14 @@ class FieldConfigEntityUnitTest extends UnitTestCase {
$container = new ContainerBuilder();
$container->set('entity.manager', $this->entityManager);
$container->set('entity_field.manager', $this->entityFieldManager);
$container->set('entity_type.manager', $this->entityTypeManager);
$container->set('uuid', $this->uuid);
$container->set('config.typed', $this->typedConfigManager);
$container->set('plugin.manager.field.field_type', $this->fieldTypePluginManager);
// Inject the container into entity.manager so it can defer to
// entity_type.manager, etc.
$this->entityManager->setContainer($container);
\Drupal::setContainer($container);
// Create a mock FieldStorageConfig object.
@@ -102,7 +126,7 @@ class FieldConfigEntityUnitTest extends UnitTestCase {
->method('getSettings')
->willReturn([]);
// Place the field in the mocked entity manager's field registry.
$this->entityManager->expects($this->any())
$this->entityFieldManager->expects($this->any())
->method('getFieldStorageDefinitions')
->with('test_entity_type')
->will($this->returnValue([
@@ -120,19 +144,19 @@ class FieldConfigEntityUnitTest extends UnitTestCase {
->method('getBundleConfigDependency')
->will($this->returnValue(['type' => 'config', 'name' => 'test.test_entity_type.id']));
$this->entityManager->expects($this->at(0))
$this->entityTypeManager->expects($this->at(0))
->method('getDefinition')
->with($this->entityTypeId)
->willReturn($this->entityType);
$this->entityManager->expects($this->at(1))
$this->entityTypeManager->expects($this->at(1))
->method('getDefinition')
->with($this->entityTypeId)
->willReturn($this->entityType);
$this->entityManager->expects($this->at(2))
$this->entityTypeManager->expects($this->at(2))
->method('getDefinition')
->with($this->entityTypeId)
->willReturn($this->entityType);
$this->entityManager->expects($this->at(3))
$this->entityTypeManager->expects($this->at(3))
->method('getDefinition')
->with('test_entity_type')
->willReturn($target_entity_type);
@@ -168,7 +192,7 @@ class FieldConfigEntityUnitTest extends UnitTestCase {
->with('test_bundle_not_exists')
->will($this->returnValue(NULL));
$this->entityManager->expects($this->any())
$this->entityTypeManager->expects($this->any())
->method('getStorage')
->with('bundle_entity_type')
->will($this->returnValue($storage));
@@ -178,19 +202,19 @@ class FieldConfigEntityUnitTest extends UnitTestCase {
'bundle_entity_type' => 'bundle_entity_type',
]);
$this->entityManager->expects($this->at(0))
$this->entityTypeManager->expects($this->at(0))
->method('getDefinition')
->with($this->entityTypeId)
->willReturn($this->entityType);
$this->entityManager->expects($this->at(1))
$this->entityTypeManager->expects($this->at(1))
->method('getDefinition')
->with($this->entityTypeId)
->willReturn($this->entityType);
$this->entityManager->expects($this->at(2))
$this->entityTypeManager->expects($this->at(2))
->method('getDefinition')
->with($this->entityTypeId)
->willReturn($this->entityType);
$this->entityManager->expects($this->at(3))
$this->entityTypeManager->expects($this->at(3))
->method('getDefinition')
->with('test_entity_type')
->willReturn($target_entity_type);
@@ -267,7 +291,7 @@ class FieldConfigEntityUnitTest extends UnitTestCase {
'dependencies' => [],
'field_type' => 'test_field',
];
$this->entityManager->expects($this->any())
$this->entityTypeManager->expects($this->any())
->method('getDefinition')
->with($this->entityTypeId)
->will($this->returnValue($this->entityType));
@@ -289,7 +313,7 @@ class FieldConfigEntityUnitTest extends UnitTestCase {
public function testGetType() {
// Ensure that FieldConfig::getType() is not delegated to
// FieldStorage.
$this->entityManager->expects($this->never())
$this->entityFieldManager->expects($this->never())
->method('getFieldStorageDefinitions');
$this->fieldStorage->expects($this->never())
->method('getType');
@@ -6,8 +6,9 @@ use Drupal\Component\Uuid\UuidInterface;
use Drupal\Core\Cache\Context\CacheContextsManager;
use Drupal\Core\Config\Entity\ConfigEntityTypeInterface;
use Drupal\Core\DependencyInjection\Container;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Entity\EntityManager;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\field\Entity\FieldStorageConfig;
@@ -52,17 +53,10 @@ class FieldStorageConfigAccessControlHandlerTest extends UnitTestCase {
protected $member;
/**
* The mocked test field storage config.
* The FieldStorageConfig entity used for testing.
*
* @var \Drupal\field\FieldStorageConfigInterface
*/
protected $fieldStorage;
/**
* The main entity used for testing.
*
* @var \Drupal\Core\Config\Entity\ConfigEntityInterface
*/
protected $entity;
/**
@@ -126,34 +120,40 @@ class FieldStorageConfigAccessControlHandlerTest extends UnitTestCase {
$storage_access_control_handler = new FieldStorageConfigAccessControlHandler($storageType);
$storage_access_control_handler->setModuleHandler($this->moduleHandler);
$entityManager = $this->getMock(EntityManagerInterface::class);
$entityManager
$entity_type_manager = $this->getMock(EntityTypeManagerInterface::class);
$entity_type_manager
->expects($this->any())
->method('getDefinition')
->willReturnMap([
['field_storage_config', TRUE, $storageType],
['node', TRUE, $entityType],
]);
$entityManager
$entity_type_manager
->expects($this->any())
->method('getStorage')
->willReturnMap([
['field_storage_config', $this->getMock(EntityStorageInterface::class)],
]);
$entityManager
$entity_type_manager
->expects($this->any())
->method('getAccessControlHandler')
->willReturnMap([
['field_storage_config', $storage_access_control_handler],
]);
$entity_manager = new EntityManager();
$container = new Container();
$container->set('entity.manager', $entityManager);
$container->set('entity.manager', $entity_manager);
$container->set('entity_type.manager', $entity_type_manager);
$container->set('uuid', $this->getMock(UuidInterface::class));
$container->set('cache_contexts_manager', $this->prophesize(CacheContextsManager::class));
// Inject the container into entity.manager so it can defer to
// entity_type.manager.
$entity_manager->setContainer($container);
\Drupal::setContainer($container);
$this->fieldStorage = new FieldStorageConfig([
$this->entity = new FieldStorageConfig([
'field_name' => 'test_field',
'entity_type' => 'node',
'type' => 'boolean',
@@ -161,7 +161,6 @@ class FieldStorageConfigAccessControlHandlerTest extends UnitTestCase {
'uuid' => '6f2f259a-f3c7-42ea-bdd5-111ad1f85ed1',
]);
$this->entity = $this->fieldStorage;
$this->accessControlHandler = $storage_access_control_handler;
}
@@ -188,7 +187,7 @@ class FieldStorageConfigAccessControlHandlerTest extends UnitTestCase {
$this->assertAllowOperations([], $this->anon);
$this->assertAllowOperations(['view', 'update', 'delete'], $this->member);
$this->fieldStorage->setLocked(TRUE)->save();
$this->entity->setLocked(TRUE)->save();
// Unfortunately, EntityAccessControlHandler has a static cache, which we
// therefore must reset manually.
$this->accessControlHandler->resetCache();
@@ -8,6 +8,8 @@
namespace Drupal\Tests\field\Unit;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\Entity\EntityManager;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Field\FieldException;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Field\FieldTypePluginManagerInterface;
@@ -22,11 +24,11 @@ use Drupal\Tests\UnitTestCase;
class FieldStorageConfigEntityUnitTest extends UnitTestCase {
/**
* The entity manager used for testing.
* The entity type manager used for testing.
*
* @var \Drupal\Core\Entity\EntityManagerInterface|\PHPUnit_Framework_MockObject_MockObject
* @var \Drupal\Core\Entity\EntityTypeManagerInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $entityManager;
protected $entityTypeManager;
/**
* The ID of the type of the entity under test.
@@ -53,14 +55,19 @@ class FieldStorageConfigEntityUnitTest extends UnitTestCase {
* {@inheritdoc}
*/
protected function setUp() {
$this->entityManager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface');
$entity_manager = new EntityManager();
$this->entityTypeManager = $this->getMock(EntityTypeManagerInterface::class);
$this->uuid = $this->getMock('\Drupal\Component\Uuid\UuidInterface');
$this->fieldTypeManager = $this->getMock(FieldTypePluginManagerInterface::class);
$container = new ContainerBuilder();
$container->set('entity.manager', $this->entityManager);
$container->set('entity.manager', $entity_manager);
$container->set('entity_type.manager', $this->entityTypeManager);
$container->set('uuid', $this->uuid);
$container->set('plugin.manager.field.field_type', $this->fieldTypeManager);
// Inject the container into entity.manager so it can defer to
// entity_type.manager.
$entity_manager->setContainer($container);
\Drupal::setContainer($container);
}
@@ -85,7 +92,7 @@ class FieldStorageConfigEntityUnitTest extends UnitTestCase {
// ConfigEntityBase::addDependency() to get the provider of the field config
// entity type and once in FieldStorageConfig::calculateDependencies() to
// get the provider of the entity type that field is attached to.
$this->entityManager->expects($this->any())
$this->entityTypeManager->expects($this->any())
->method('getDefinition')
->willReturnMap([
['field_storage_config', TRUE, $fieldStorageConfigentityType],
@@ -0,0 +1,26 @@
<?php
namespace Drupal\Tests\field\Unit\Plugin\migrate\process;
use Drupal\field\Plugin\migrate\process\FieldTypeDefaults;
use Drupal\Tests\migrate\Unit\process\MigrateProcessTestCase;
/**
* Tests the deprecation of the field_type_defaults process plugin.
*
* @coversDefaultClass \Drupal\field\Plugin\migrate\process\FieldTypeDefaults
* @group field
* @group legacy
*/
class FieldTypeDefaultsTest extends MigrateProcessTestCase {
/**
* Tests that the field_type_defaults plugin triggers a deprecation error.
*
* @expectedDeprecation The field_type_defaults process plugin is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. Use d6_field_type_defaults or d7_field_type_defaults instead. See https://www.drupal.org/node/2944589.
*/
public function testDeprecatedError() {
$this->plugin = new FieldTypeDefaults([], 'field_type_defaults', []);
}
}
@@ -19,7 +19,7 @@ class FieldTypeDefaultsTest extends MigrateProcessTestCase {
*/
protected function setUp() {
parent::setUp();
$this->plugin = new FieldTypeDefaults([], 'field_type_defaults', []);
$this->plugin = new FieldTypeDefaults([], 'd6_field_type_defaults', []);
}
/**
@@ -0,0 +1,39 @@
<?php
namespace Drupal\Tests\field\Unit\Plugin\migrate\process\d7;
use Drupal\field\Plugin\migrate\process\d7\FieldTypeDefaults;
use Drupal\Tests\migrate\Unit\process\MigrateProcessTestCase;
/**
* Tests D7 field formatter defaults.
*
* @coversDefaultClass \Drupal\field\Plugin\migrate\process\d7\FieldTypeDefaults
* @group field
*/
class FieldTypeDefaultsTest extends MigrateProcessTestCase {
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->plugin = new FieldTypeDefaults([], 'd7_field_type_defaults', []);
}
/**
* Tests various default cases.
*
* @covers ::transform
*/
public function testDefaults() {
// Assert common values are passed through without modification.
$this->assertNull($this->plugin->transform(NULL, $this->migrateExecutable, $this->row, 'property'));
$this->assertEquals('string', $this->plugin->transform('string', $this->migrateExecutable, $this->row, 'property'));
$this->assertEquals(1234, $this->plugin->transform(1234, $this->migrateExecutable, $this->row, 'property'));
// Assert that an array will return the second item, which is the source
// formatter type.
$this->assertEquals('datetime_default', $this->plugin->transform(['datetime', 'datetime_default'], $this->migrateExecutable, $this->row, 'property'));
}
}