Update Composer, update everything

This commit is contained in:
Oliver Davies 2018-11-23 12:29:20 +00:00
parent ea3e94409f
commit dda5c284b6
19527 changed files with 1135420 additions and 351004 deletions

View file

@ -43,7 +43,6 @@
* @see plugin_api
*/
/**
* Perform alterations on Field API field types.
*
@ -58,6 +57,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,8 +163,14 @@ 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 hook_field_widget_form().
* The field widget form element as constructed by
* \Drupal\Core\Field\WidgetBaseInterface::form().
* @param $form_state
* The current state of the form.
* @param $context
@ -152,8 +184,10 @@ function hook_field_widget_info_alter(array &$info) {
* - 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::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.
@ -171,16 +205,24 @@ 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 hook_field_widget_form().
* The field widget form element as constructed by
* \Drupal\Core\Field\WidgetBaseInterface::form().
* @param $form_state
* The current state of the form.
* @param $context
* An associative array. See hook_field_widget_form_alter() for the structure
* and content of the array.
*
* @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,
@ -189,6 +231,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 autocomplete 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".
*/

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);
}

View file

@ -74,7 +74,7 @@ function field_help($route_name, RouteMatchInterface $route_match) {
$output .= '<h3>' . t('Terminology') . '</h3>';
$output .= '<dl>';
$output .= '<dt>' . t('Entities and entity types') . '</dt>';
$output .= '<dd>' . t('The website\'s content and configuration is managed using <em>entities</em>, which are grouped into <em>entity types</em>. <em>Content entity types</em> are the entity types for site content (such as the main site content, comments, custom blocks, taxonomy terms, and user accounts). <em>Configuration entity types</em> are used to store configuration information for your site, such as individual views in the Views module, and settings for your main site content types.') . '</dd>';
$output .= '<dd>' . t("The website's content and configuration is managed using <em>entities</em>, which are grouped into <em>entity types</em>. <em>Content entity types</em> are the entity types for site content (such as the main site content, comments, custom blocks, taxonomy terms, and user accounts). <em>Configuration entity types</em> are used to store configuration information for your site, such as individual views in the Views module, and settings for your main site content types.") . '</dd>';
$output .= '<dt>' . t('Entity sub-types') . '</dt>';
$output .= '<dd>' . t('Some content entity types are further grouped into sub-types (for example, you could have article and page content types within the main site content entity type, and tag and category vocabularies within the taxonomy term entity type); other entity types, such as user accounts, do not have sub-types. Programmers use the term <em>bundle</em> for entity sub-types.') . '</dd>';
$output .= '<dt>' . t('Fields and field types') . '</dt>';
@ -250,19 +250,6 @@ function field_entity_bundle_delete($entity_type_id, $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 critical 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()
]);
}
}
}
}
@ -337,12 +324,12 @@ function field_form_config_admin_import_form_alter(&$form, FormStateInterface $f
foreach ($field_storages as $field) {
$field_labels[] = $field->label();
}
drupal_set_message(\Drupal::translation()->formatPlural(
\Drupal::messenger()->addWarning(\Drupal::translation()->formatPlural(
count($field_storages),
'This synchronization will delete data from the field %fields.',
'This synchronization will delete data from the fields: %fields.',
['%fields' => implode(', ', $field_labels)]
), 'warning');
));
}
}
}
@ -407,4 +394,17 @@ function field_field_config_presave(FieldConfigInterface $field) {
$selection_manager = \Drupal::service('plugin.manager.entity_reference_selection');
list($current_handler) = explode(':', $field->getSetting('handler'), 2);
$field->setSetting('handler', $selection_manager->getPluginId($target_type, $current_handler));
// In case we removed all the target bundles allowed by the field in
// EntityReferenceItem::onDependencyRemoval() or field_entity_bundle_delete()
// we have to log a critical message because the field will not function
// correctly anymore.
$handler_settings = $field->getSetting('handler_settings');
if (isset($handler_settings['target_bundles']) && $handler_settings['target_bundles'] === []) {
\Drupal::logger('entity_reference')->critical('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.', [
'%field_name' => $field->getName(),
'%entity_type' => $field->getTargetEntityTypeId(),
'%bundle' => $field->getTargetBundle(),
]);
}
}

View file

@ -6,10 +6,10 @@
*/
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\field\Entity\FieldConfig;
/**
* Re-save all field storage config objects to add 'custom_storage' property.
*/
@ -59,3 +59,26 @@ function field_post_update_email_widget_size_setting() {
return t('The new size setting for email widgets has been added.');
}
/**
* Remove the stale 'handler_submit' setting for entity_reference fields.
*/
function field_post_update_remove_handler_submit_setting() {
$config = \Drupal::configFactory();
/** @var \Drupal\Core\Field\FieldTypePluginManager $field_type_manager */
$field_type_manager = \Drupal::service('plugin.manager.field.field_type');
// Iterate on all field configs.
foreach ($config->listAll('field.field.') as $field_id) {
$field = $config->getEditable($field_id);
$class = $field_type_manager->getPluginClass($field->get('field_type'));
// Deal only with entity reference fields and descendants.
if ($class === EntityReferenceItem::class || is_subclass_of($class, EntityReferenceItem::class)) {
if ($field->get('settings.handler_submit')) {
// Remove 'handler_settings' from settings.
$field->clear('settings.handler_submit')->save();
}
}
}
}

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);

View file

@ -2,8 +2,9 @@ id: d6_field
label: Field configuration
migration_tags:
- Drupal 6
class: Drupal\migrate_drupal\Plugin\migrate\CckMigration
cck_plugin_method: processField
- Configuration
class: Drupal\migrate_drupal\Plugin\migrate\FieldMigration
field_plugin_method: alterFieldMigration
source:
plugin: d6_field
constants:

View file

@ -2,8 +2,9 @@ id: d6_field_formatter_settings
label: Field formatter configuration
migration_tags:
- Drupal 6
class: Drupal\migrate_drupal\Plugin\migrate\CckMigration
cck_plugin_method: processFieldFormatter
- Configuration
class: Drupal\migrate_drupal\Plugin\migrate\FieldMigration
field_plugin_method: alterFieldFormatterMigration
source:
plugin: d6_field_instance_per_view_mode
constants:
@ -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

View file

@ -2,8 +2,9 @@ id: d6_field_instance
label: Field instance configuration
migration_tags:
- Drupal 6
class: Drupal\migrate_drupal\Plugin\migrate\CckMigration
cck_plugin_method: processFieldInstance
- Configuration
class: Drupal\migrate_drupal\Plugin\migrate\FieldMigration
field_plugin_method: alterFieldInstanceMigration
source:
plugin: d6_field_instance
constants:

View file

@ -2,8 +2,9 @@ id: d6_field_instance_widget_settings
label: Field instance widget configuration
migration_tags:
- Drupal 6
class: Drupal\migrate_drupal\Plugin\migrate\CckMigration
cck_plugin_method: processFieldWidget
- Configuration
class: Drupal\migrate_drupal\Plugin\migrate\FieldMigration
field_plugin_method: alterFieldWidgetMigration
source:
plugin: d6_field_instance_per_form_display
constants:
@ -56,6 +57,8 @@ process:
optionwidgets_buttons: options_buttons
optionwidgets_select: options_select
nodereference_select: options_select
nodereference_buttons: options_buttons
nodereference_autocomplete: entity_reference_autocomplete_tags
userreference_select: options_select
'options/settings':
-

View file

@ -2,8 +2,9 @@ id: d7_field
label: Field configuration
migration_tags:
- Drupal 7
class: Drupal\migrate_drupal\Plugin\migrate\CckMigration
cck_plugin_method: processField
- Configuration
class: Drupal\migrate_drupal\Plugin\migrate\FieldMigration
field_plugin_method: alterFieldMigration
source:
plugin: d7_field
constants:
@ -15,26 +16,9 @@ process:
langcode: 'constants/langcode'
field_name: field_name
type:
plugin: field_type
plugin: process_field
source: type
map:
date: datetime
datestamp: datetime
datetime: datetime
email: email
entityreference: entity_reference
file: file
image: image
link_field: link
list_boolean: boolean
list_integer: list_integer
list_text: list_string
number_integer: integer
number_decimal: decimal
number_float: float
phone: telephone
text_long: text_long
text_with_summary: text_with_summary
method: getFieldType
# Translatable is not migrated and the Drupal 8 default of true is used.
# If translatable is false in field storage then the field can not be
# set to translatable via the UI.

View file

@ -2,8 +2,9 @@ id: d7_field_formatter_settings
label: Field formatter configuration
migration_tags:
- Drupal 7
class: Drupal\migrate_drupal\Plugin\migrate\CckMigration
cck_plugin_method: processFieldFormatter
- Configuration
class: Drupal\migrate_drupal\Plugin\migrate\FieldMigration
field_plugin_method: alterFieldFormatterMigration
source:
plugin: d7_field_instance_per_view_mode
constants:
@ -26,7 +27,15 @@ process:
plugin: skip_on_empty
method: row
entity_type: entity_type
bundle: bundle
# The bundle needs to be statically mapped in order to support comment types
# that might already exist before this migration is run. See
# d7_comment_type.yml or more information.
bundle:
plugin: static_map
source: bundle
bypass: true
map:
comment_node_forum: comment_forum
view_mode:
-
plugin: migration_lookup
@ -44,32 +53,36 @@ process:
map:
full: default
field_name: field_name
"options/label": label
"options/weight": weight
"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
source: type
method: getFieldFormatterType
"options/type":
-
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
"options/settings":
plugin: default_value
source: settings
source: 'formatter/settings'
default_value: []
"options/third_party_settings": 'constants/third_party_settings'
destination:

View file

@ -2,16 +2,29 @@ id: d7_field_instance
label: Field instance configuration
migration_tags:
- Drupal 7
class: Drupal\migrate_drupal\Plugin\migrate\CckMigration
cck_plugin_method: processFieldInstance
- Configuration
class: Drupal\migrate_drupal\Plugin\migrate\FieldMigration
field_plugin_method: alterFieldInstanceMigration
source:
plugin: d7_field_instance
constants:
status: true
process:
type:
plugin: process_field
source: type
method: getFieldType
entity_type: entity_type
field_name: field_name
bundle: bundle
# The bundle needs to be statically mapped in order to support comment types
# that might already exist before this migration is run. See
# d7_comment_type.yml for more information.
bundle:
plugin: static_map
source: bundle
bypass: true
map:
comment_node_forum: comment_forum
label: label
description: description
required: required
@ -19,15 +32,15 @@ process:
settings:
plugin: d7_field_instance_settings
source:
- instance_settings
- widget_settings
- field_settings
- settings
- widget
- field_definition
default_value_function: ''
default_value:
plugin: d7_field_instance_defaults
source:
- default_value
- widget_settings
- widget
translatable: translatable
destination:
plugin: entity:field_config

View file

@ -2,8 +2,9 @@ id: d7_field_instance_widget_settings
label: Field instance widget configuration
migration_tags:
- Drupal 7
class: Drupal\migrate_drupal\Plugin\migrate\CckMigration
cck_plugin_method: processFieldWidget
- Configuration
class: Drupal\migrate_drupal\Plugin\migrate\FieldMigration
field_plugin_method: alterFieldWidgetMigration
source:
plugin: d7_field_instance_per_form_display
constants:
@ -26,16 +27,28 @@ process:
-
plugin: skip_on_empty
method: row
bundle: bundle
# The bundle needs to be statically mapped in order to support comment types
# that might already exist before this migration is run. See
# d7_comment_type.yml for more information.
bundle:
plugin: static_map
source: bundle
bypass: true
map:
comment_node_forum: comment_forum
form_mode: 'constants/form_mode'
field_name: field_name
entity_type: entity_type
'options/weight': 'widget/weight'
widget_type:
plugin: process_field
source: type
method: getFieldWidgetType
'options/type':
type:
plugin: static_map
bypass: true
source: 'widget/type'
source: '@widget_type'
map:
link_field: link_default
email_textfield: email_default
@ -52,7 +65,7 @@ process:
plugin: field_instance_widget_settings
source:
- 'widget/type'
- widget_settings
- 'widget/settings'
'options/third_party_settings': 'constants/third_party_settings'
destination:
plugin: component_entity_form_display

View file

@ -2,6 +2,7 @@ id: d7_view_modes
label: View modes
migration_tags:
- Drupal 7
- Configuration
source:
plugin: d7_view_mode
process:

View file

@ -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;

View file

@ -3,6 +3,7 @@
namespace Drupal\field\Entity;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\FieldableEntityStorageInterface;
use Drupal\Core\Field\FieldConfigBase;
use Drupal\Core\Field\FieldException;
use Drupal\field\FieldStorageConfigInterface;
@ -14,6 +15,13 @@ use Drupal\field\FieldConfigInterface;
* @ConfigEntityType(
* id = "field_config",
* label = @Translation("Field"),
* label_collection = @Translation("Fields"),
* label_singular = @Translation("field"),
* label_plural = @Translation("fields"),
* label_count = @PluralTranslation(
* singular = "@count field",
* plural = "@count fields",
* ),
* handlers = {
* "access" = "Drupal\field\FieldConfigAccessControlHandler",
* "storage" = "Drupal\field\FieldConfigStorage"
@ -188,21 +196,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) {
if (!$field->deleted) {
$config = $field->toArray();
$config['deleted'] = TRUE;
$config['field_storage_uuid'] = $field->getFieldStorageDefinition()->uuid();
$deleted_fields[$field->uuid()] = $config;
// 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)) {
$field = clone $field;
$field->deleted = TRUE;
$field->fieldStorage = NULL;
$deleted_fields_repository->addFieldDefinition($field);
}
}
$state->set('field.field.deleted', $deleted_fields);
}
/**
@ -281,14 +294,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;
@ -323,6 +352,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.
*

View file

@ -2,10 +2,10 @@
namespace Drupal\field\Entity;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Config\Entity\ConfigEntityBase;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Entity\FieldableEntityStorageInterface;
use Drupal\Core\Field\FieldException;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\TypedData\OptionsProviderInterface;
@ -17,6 +17,13 @@ use Drupal\field\FieldStorageConfigInterface;
* @ConfigEntityType(
* id = "field_storage_config",
* label = @Translation("Field storage"),
* label_collection = @Translation("Field storages"),
* label_singular = @Translation("field storage"),
* label_plural = @Translation("field storages"),
* label_count = @PluralTranslation(
* singular = "@count field storage",
* plural = "@count field storages",
* ),
* handlers = {
* "access" = "Drupal\field\FieldStorageConfigAccessControlHandler",
* "storage" = "Drupal\field\FieldStorageConfigStorage"
@ -309,10 +316,10 @@ class FieldStorageConfig extends ConfigEntityBase implements FieldStorageConfigI
// Assign the ID.
$this->id = $this->id();
// Field name cannot be longer than FieldStorageConfig::NAME_MAX_LENGTH characters.
// We use Unicode::strlen() because the DB layer assumes that column widths
// are given in characters rather than bytes.
if (Unicode::strlen($this->getName()) > static::NAME_MAX_LENGTH) {
// Field name cannot be longer than FieldStorageConfig::NAME_MAX_LENGTH
// characters. We use mb_strlen() because the DB layer assumes that column
// widths are given in characters rather than bytes.
if (mb_strlen($this->getName()) > static::NAME_MAX_LENGTH) {
throw new FieldException('Attempt to create a field storage with an name longer than ' . static::NAME_MAX_LENGTH . ' characters: ' . $this->getName());
}
@ -397,7 +404,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.
@ -406,19 +414,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) {
if (!$field_storage->deleted) {
$config = $field_storage->toArray();
$config['deleted'] = TRUE;
$config['bundles'] = $field_storage->getBundles();
$deleted_storages[$field_storage->uuid()] = $config;
// 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)) {
$storage_definition = clone $field_storage;
$storage_definition->deleted = TRUE;
$deleted_fields_repository->addFieldStorageDefinition($storage_definition);
}
}
$state->set('field.storage.deleted', $deleted_storages);
}
/**
@ -628,7 +636,17 @@ class FieldStorageConfig extends ConfigEntityBase implements FieldStorageConfigI
* {@inheritdoc}
*/
public function getCardinality() {
return $this->cardinality;
/** @var \Drupal\Core\Field\FieldTypePluginManager $field_type_manager */
$field_type_manager = \Drupal::service('plugin.manager.field.field_type');
$definition = $field_type_manager->getDefinition($this->getType());
$enforced_cardinality = isset($definition['cardinality']) ? $definition['cardinality'] : NULL;
// Enforced cardinality is a positive integer or -1.
if ($enforced_cardinality !== NULL && $enforced_cardinality < 1 && $enforced_cardinality !== FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) {
throw new FieldException("Invalid enforced cardinality '$enforced_cardinality'. Allowed values: a positive integer or -1.");
}
return $enforced_cardinality ?: $this->cardinality;
}
/**

View file

@ -2,19 +2,20 @@
namespace Drupal\field;
use Drupal\Core\Cache\MemoryCache\MemoryCacheInterface;
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 +26,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 +33,13 @@ class FieldConfigStorage extends FieldConfigStorageBase {
*/
protected $fieldTypeManager;
/**
* The deleted fields repository.
*
* @var \Drupal\Core\Field\DeletedFieldsRepositoryInterface
*/
protected $deletedFieldsRepository;
/**
* Constructs a FieldConfigStorage object.
*
@ -52,16 +53,18 @@ 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.
* @param \Drupal\Core\Cache\MemoryCache\MemoryCacheInterface $memory_cache
* The memory cache.
*/
public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, UuidInterface $uuid_service, LanguageManagerInterface $language_manager, EntityManagerInterface $entity_manager, StateInterface $state, FieldTypePluginManagerInterface $field_type_manager) {
parent::__construct($entity_type, $config_factory, $uuid_service, $language_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, MemoryCacheInterface $memory_cache) {
parent::__construct($entity_type, $config_factory, $uuid_service, $language_manager, $memory_cache);
$this->entityManager = $entity_manager;
$this->state = $state;
$this->fieldTypeManager = $field_type_manager;
$this->deletedFieldsRepository = $deleted_fields_repository;
}
/**
@ -74,8 +77,9 @@ 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'),
$container->get('entity.memory_cache')
);
}
@ -104,7 +108,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 +121,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);
}
}

View file

@ -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.
*

View file

@ -3,19 +3,20 @@
namespace Drupal\field;
use Drupal\Component\Uuid\UuidInterface;
use Drupal\Core\Cache\MemoryCache\MemoryCacheInterface;
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 +34,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 +41,13 @@ class FieldStorageConfigStorage extends ConfigEntityStorage {
*/
protected $fieldTypeManager;
/**
* The deleted fields repository.
*
* @var \Drupal\Core\Field\DeletedFieldsRepositoryInterface
*/
protected $deletedFieldsRepository;
/**
* Constructs a FieldStorageConfigStorage object.
*
@ -62,17 +63,19 @@ 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.
* @param \Drupal\Core\Cache\MemoryCache\MemoryCacheInterface $memory_cache
* The memory cache.
*/
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) {
parent::__construct($entity_type, $config_factory, $uuid_service, $language_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, MemoryCacheInterface $memory_cache) {
parent::__construct($entity_type, $config_factory, $uuid_service, $language_manager, $memory_cache);
$this->entityManager = $entity_manager;
$this->moduleHandler = $module_handler;
$this->state = $state;
$this->fieldTypeManager = $field_type_manager;
$this->deletedFieldsRepository = $deleted_fields_repository;
}
/**
@ -86,8 +89,9 @@ 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'),
$container->get('entity.memory_cache')
);
}
@ -104,7 +108,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 +121,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;
}
}
}

View file

@ -85,7 +85,6 @@ class FieldUninstallValidator implements ModuleUninstallValidatorInterface {
return $this->fieldStorageConfigStorage->loadByProperties(['module' => $module, 'include_deleted' => TRUE]);
}
/**
* Returns the label for a specified field type.
*

View file

@ -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 {}

View file

@ -0,0 +1,155 @@
<?php
namespace Drupal\field\Plugin\migrate\process;
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\migrate\MigrateException;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\Plugin\MigrationInterface;
use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\Row;
use Drupal\migrate_drupal\Plugin\MigrateCckFieldPluginManagerInterface;
use Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Get the value from a method call on a field plugin instance.
*
* This process plugin will instantiate a field plugin based on the given
* field type and then call the given method on it for the return value.
*
* Available configuration keys:
* - source: The source field type to use to instantiate a field plugin.
* - method: The method to be called on the field plugin instance.
*
* If no field plugin for the given field type is found, NULL will be returned.
*
* Example:
*
* @code
* process:
* type:
* plugin: process_field
* source: type
* method: getFieldType
* @endcode
*
* @see \Drupal\migrate\Plugin\MigrateProcessInterface
* @see \Drupal\migrate_drupal\Plugin\MigrateFieldInterface;
*
* @MigrateProcessPlugin(
* id = "process_field"
* )
*/
class ProcessField extends ProcessPluginBase implements ContainerFactoryPluginInterface {
/**
* The cckfield plugin manager.
*
* @var \Drupal\migrate_drupal\Plugin\MigrateCckFieldPluginManagerInterface
*/
protected $cckPluginManager;
/**
* The field plugin manager.
*
* @var \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface
*/
protected $fieldPluginManager;
/**
* The migration being run.
*
* @var \Drupal\migrate\Plugin\MigrationInterface
*/
protected $migration;
/**
* Constructs a ProcessField plugin.
*
* @param array $configuration
* The plugin configuration.
* @param string $plugin_id
* The plugin ID.
* @param mixed $plugin_definition
* The plugin definition.
* @param \Drupal\migrate_drupal\Plugin\MigrateCckFieldPluginManagerInterface $cck_plugin_manager
* The cckfield plugin manager.
* @param \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface $field_plugin_manager
* The field plugin manager.
* @param \Drupal\migrate\Plugin\MigrationInterface $migration
* The migration being run.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrateCckFieldPluginManagerInterface $cck_plugin_manager, MigrateFieldPluginManagerInterface $field_plugin_manager, MigrationInterface $migration = NULL) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->cckPluginManager = $cck_plugin_manager;
$this->fieldPluginManager = $field_plugin_manager;
$this->migration = $migration;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('plugin.manager.migrate.cckfield'),
$container->get('plugin.manager.migrate.field'),
$migration
);
}
/**
* {@inheritdoc}
*/
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
if (!is_string($value)) {
throw new MigrateException('The input value must be a string.');
}
if (empty($this->configuration['method'])) {
throw new MigrateException('You need to specify the name of a method to be called on the Field plugin.');
}
$method = $this->configuration['method'];
try {
return $this->callMethodOnFieldPlugin($this->fieldPluginManager, $value, $method, $row);
}
catch (PluginNotFoundException $e) {
try {
return $this->callMethodOnFieldPlugin($this->cckPluginManager, $value, $method, $row);
}
catch (PluginNotFoundException $e) {
return NULL;
}
}
}
/**
* Instantiate a field plugin and call a method on it.
*
* @param \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface $field_plugin_manager
* The field plugin manager.
* @param string $field_type
* The field type for which to get the field plugin.
* @param string $method
* The method to call on the field plugin.
* @param \Drupal\migrate\Row $row
* The row from the source to process.
*
* @return mixed
* The return value from the method called on the field plugin.
*/
protected function callMethodOnFieldPlugin(MigrateFieldPluginManagerInterface $field_plugin_manager, $field_type, $method, Row $row) {
$plugin_id = $field_plugin_manager->getPluginIdFromFieldType($field_type, [], $this->migration);
$plugin_instance = $field_plugin_manager->createInstance($plugin_id, [], $this->migration);
if (!is_callable([$plugin_instance, $method])) {
throw new MigrateException('The specified method does not exist or is not callable.');
}
return call_user_func_array([$plugin_instance, $method], [$row]);
}
}

View file

@ -0,0 +1,53 @@
<?php
namespace Drupal\field\Plugin\migrate\process\d6;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\Row;
/**
* Determines the settings property and translation for boolean fields.
*
* @MigrateProcessPlugin(
* id = "d6_field_instance_option_translation",
* handle_multiples = TRUE
* )
*/
class FieldInstanceOptionTranslation extends ProcessPluginBase {
/**
* {@inheritdoc}
*/
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
list($field_type, $global_settings) = $value;
$option_key = 0;
$translation = '';
if (isset($global_settings['allowed_values'])) {
$list = explode("\n", $global_settings['allowed_values']);
$list = array_map('trim', $list);
$list = array_filter($list, 'strlen');
switch ($field_type) {
case 'boolean';
$option = preg_replace('/^option_/', '', $row->getSourceProperty('property'));
for ($i = 0; $i < 2; $i++) {
$value = $list[$i];
$tmp = explode("|", $value);
$original_option_key = isset($tmp[0]) ? $tmp[0] : NULL;
$option_key = ($i === 0) ? 'off_label' : 'on_label';
// Find property with name matching the original option.
if ($option == $original_option_key) {
$translation = $row->getSourceProperty('translation');
break;
}
}
break;
default:
}
}
return ['settings.' . $option_key, $translation];
}
}

View file

@ -0,0 +1,59 @@
<?php
namespace Drupal\field\Plugin\migrate\process\d6;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\Row;
/**
* Determines the allowed values translation for select lists.
*
* @MigrateProcessPlugin(
* id = "d6_field_option_translation",
* handle_multiples = TRUE
* )
*/
class FieldOptionTranslation extends ProcessPluginBase {
/**
* {@inheritdoc}
*
* Get the field default/mapped settings.
*/
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
list($field_type, $global_settings) = $value;
$allowed_values = '';
$i = 0;
if (isset($global_settings['allowed_values'])) {
$list = explode("\n", $global_settings['allowed_values']);
$list = array_map('trim', $list);
$list = array_filter($list, 'strlen');
switch ($field_type) {
case 'list_string':
case 'list_integer':
case 'list_float':
// Remove the prefix used in the i18n_strings table for field options
// to get the option value.
$option = preg_replace('/^option_/', '', $row->getSourceProperty('property'));
$i = 0;
foreach ($list as $allowed_value) {
// Get the key for this allowed value which may be a key|label pair
// or or just key.
$value = explode("|", $allowed_value);
if (isset($value[0]) && ($value[0] == $option)) {
$allowed_values = ['label' => $row->getSourceProperty('translation')];
break;
}
$i++;
}
break;
default:
}
}
return ["settings.allowed_values.$i", $allowed_values];
}
}

View file

@ -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 {

View file

@ -19,18 +19,16 @@ class FieldInstanceDefaults extends ProcessPluginBase {
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
list($default_value, $widget_settings) = $value;
$widget_type = $widget_settings['type'];
$default_value = $default_value ?: [];
$default = [];
foreach ($default_value as $item) {
switch ($widget_type) {
// Add special processing here if needed.
default:
$default[] = $item;
}
// In Drupal 7, the default value for email fields is stored in the key
// 'email' while in Drupal 8 it is stored in the key 'value'.
if ($widget_type == 'email_textfield' && $default_value) {
$default_value[0]['value'] = $default_value[0]['email'];
unset($default_value[0]['email']);
}
return $default;
return $default_value;
}
}

View file

@ -17,9 +17,12 @@ class FieldInstanceSettings extends ProcessPluginBase {
* {@inheritdoc}
*/
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
list($instance_settings, $widget_settings, $field_settings) = $value;
list($instance_settings, $widget_settings, $field_definition) = $value;
$widget_type = $widget_settings['type'];
$field_data = unserialize($field_definition['data']);
$field_settings = $field_data['settings'];
// Get entityreference handler settings from source field configuration.
if ($row->getSourceProperty('type') == "entityreference") {
$instance_settings['handler'] = 'default:' . $field_settings['target_type'];

View file

@ -26,6 +26,16 @@ class FieldSettings extends ProcessPluginBase {
}
break;
case 'date':
case 'datetime':
case 'datestamp':
if ($value['granularity']['hour'] === 0
&& $value['granularity']['minute'] === 0
&& $value['granularity']['second'] === 0) {
$value['datetime_type'] = 'date';
}
break;
case 'taxonomy_term_reference':
$value['target_type'] = 'taxonomy_term';
break;

View file

@ -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;
}
}

View file

@ -10,7 +10,7 @@ use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
*
* @MigrateSource(
* id = "d6_field",
* source_provider = "content"
* source_module = "content"
* )
*/
class Field extends DrupalSqlBase {

View file

@ -10,7 +10,7 @@ use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
*
* @MigrateSource(
* id = "d6_field_instance",
* source_provider = "content"
* source_module = "content"
* )
*/
class FieldInstance extends DrupalSqlBase {

View file

@ -0,0 +1,35 @@
<?php
namespace Drupal\field\Plugin\migrate\source\d6;
/**
* Gets field instance option label translations.
*
* @MigrateSource(
* id = "d6_field_instance_option_translation",
* source_module = "i18ncck"
* )
*/
class FieldInstanceOptionTranslation extends FieldOptionTranslation {
/**
* {@inheritdoc}
*/
public function query() {
$query = parent::query();
$query->join('content_node_field_instance', 'cnfi', 'cnf.field_name = cnfi.field_name');
$query->addField('cnfi', 'type_name');
return $query;
}
/**
* {@inheritdoc}
*/
public function fields() {
$fields = [
'type_name' => $this->t('Type (article, page, ....)'),
];
return parent::fields() + $fields;
}
}

View file

@ -9,7 +9,7 @@ use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
*
* @MigrateSource(
* id = "d6_field_instance_per_form_display",
* source_provider = "content"
* source_module = "content"
* )
*/
class FieldInstancePerFormDisplay extends DrupalSqlBase {

View file

@ -9,7 +9,7 @@ use Drupal\node\Plugin\migrate\source\d6\ViewModeBase;
*
* @MigrateSource(
* id = "d6_field_instance_per_view_mode",
* source_provider = "content"
* source_module = "content"
* )
*/
class FieldInstancePerViewMode extends ViewModeBase {

View file

@ -0,0 +1,60 @@
<?php
namespace Drupal\field\Plugin\migrate\source\d6;
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
/**
* Gets field label and description translations.
*
* @MigrateSource(
* id = "d6_field_instance_label_description_translation",
* source_module = "i18ncck"
* )
*/
class FieldLabelDescriptionTranslation extends DrupalSqlBase {
/**
* {@inheritdoc}
*/
public function query() {
// Get translations for field labels and descriptions.
$query = $this->select('i18n_strings', 'i18n')
->fields('i18n', ['property', 'objectid', 'type'])
->fields('lt', ['lid', 'translation', 'language'])
->condition('i18n.type', 'field')
->isNotNull('language')
->isNotNull('translation');
$condition = $query->orConditionGroup()
->condition('property', 'widget_label')
->condition('property', 'widget_description');
$query->condition($condition);
$query->leftJoin('locales_target', 'lt', 'lt.lid = i18n.lid');
return $query;
}
/**
* {@inheritdoc}
*/
public function fields() {
return [
'property' => $this->t('Profile field ID.'),
'lid' => $this->t('Locales target language ID.'),
'language' => $this->t('Language for this field.'),
'translation' => $this->t('Translation of either the title or explanation.'),
];
}
/**
* {@inheritdoc}
*/
public function getIds() {
$ids['property']['type'] = 'string';
$ids['language']['type'] = 'string';
$ids['lid']['type'] = 'integer';
$ids['lid']['alias'] = 'lt';
return $ids;
}
}

View file

@ -0,0 +1,78 @@
<?php
namespace Drupal\field\Plugin\migrate\source\d6;
/**
* Gets field option label translations.
*
* @MigrateSource(
* id = "d6_field_option_translation",
* source_module = "i18ncck"
* )
*/
class FieldOptionTranslation extends Field {
/**
* {@inheritdoc}
*/
public function query() {
// Get the fields that have field options translations.
$query = $this->select('i18n_strings', 'i18n')
->fields('i18n')
->fields('lt', [
'translation',
'language',
'plid',
'plural',
'i18n_status',
])
->condition('i18n.type', 'field')
->condition('property', 'option\_%', 'LIKE')
->isNotNull('translation');
$query->leftJoin('locales_target', 'lt', 'lt.lid = i18n.lid');
$query->leftjoin('content_node_field', 'cnf', 'cnf.field_name = i18n.objectid');
$query->addField('cnf', 'field_name');
$query->addField('cnf', 'global_settings');
// Minimise changes to the d6_field_option_translation.yml, which is copied
// from d6_field.yml, by ensuring the 'type' property is from
// content_node_field table.
$query->addField('cnf', 'type');
$query->addField('i18n', 'type', 'i18n_type');
return $query;
}
/**
* {@inheritdoc}
*/
public function fields() {
$fields = [
'property' => $this->t('Option ID.'),
'objectid' => $this->t('Object ID'),
'objectindex' => $this->t('Integer value of Object ID'),
'format' => $this->t('The input format used by this string'),
'lid' => $this->t('Source string ID'),
'language' => $this->t('Language code'),
'translation' => $this->t('Translation of the option'),
'plid' => $this->t('Parent lid'),
'plural' => $this->t('Plural index number in case of plural strings'),
];
return parent::fields() + $fields;
}
/**
* {@inheritdoc}
*/
/**
* {@inheritdoc}
*/
public function getIds() {
return parent::getIds() +
[
'language' => ['type' => 'string'],
'property' => ['type' => 'string'],
];
}
}

View file

@ -8,8 +8,14 @@ use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
/**
* Drupal 7 field source from database.
*
* @internal
*
* This class is marked as internal and should not be extended. Use
* Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase instead.
*
* @MigrateSource(
* id = "d7_field"
* id = "d7_field",
* source_module = "field_sql_storage"
* )
*/
class Field extends DrupalSqlBase {
@ -23,10 +29,24 @@ class Field extends DrupalSqlBase {
->fields('fc')
->fields('fci', ['entity_type'])
->condition('fc.active', 1)
->condition('fc.storage_active', 1)
->condition('fc.deleted', 0)
->condition('fc.storage_active', 1);
->condition('fci.deleted', 0);
$query->join('field_config_instance', 'fci', 'fc.id = fci.field_id');
// If the Drupal 7 Title module is enabled, we don't want to migrate the
// fields it provides. The values of those fields will be migrated to the
// base fields they were replacing.
if ($this->moduleExists('title')) {
$title_fields = [
'title_field',
'name_field',
'description_field',
'subject_field',
];
$query->condition('fc.field_name', $title_fields, 'NOT IN');
}
return $query;
}
@ -35,13 +55,20 @@ class Field extends DrupalSqlBase {
*/
public function fields() {
return [
'field_name' => $this->t('The name of this field.'),
'type' => $this->t('The type of this field.'),
'id' => $this->t('The field ID.'),
'field_name' => $this->t('The field name.'),
'type' => $this->t('The field type.'),
'module' => $this->t('The module that implements the field type.'),
'storage' => $this->t('The field storage.'),
'active' => $this->t('The field status.'),
'storage_type' => $this->t('The field storage type.'),
'storage_module' => $this->t('The module that implements the field storage type.'),
'storage_active' => $this->t('The field storage status.'),
'locked' => $this->t('Locked'),
'data' => $this->t('The field data.'),
'cardinality' => $this->t('Cardinality'),
'translatable' => $this->t('Translatable'),
'deleted' => $this->t('Deleted'),
'instances' => $this->t('The field instances.'),
];
}
@ -52,6 +79,15 @@ class Field extends DrupalSqlBase {
foreach (unserialize($row->getSourceProperty('data')) as $key => $value) {
$row->setSourceProperty($key, $value);
}
$instances = $this->select('field_config_instance', 'fci')
->fields('fci')
->condition('field_name', $row->getSourceProperty('field_name'))
->condition('entity_type', $row->getSourceProperty('entity_type'))
->execute()
->fetchAll();
$row->setSourceProperty('instances', $instances);
return parent::prepareRow($row);
}

View file

@ -8,9 +8,14 @@ use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
/**
* Drupal 7 field instances source from database.
*
* @internal
*
* This class is marked as internal and should not be extended. Use
* Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase instead.
*
* @MigrateSource(
* id = "d7_field_instance",
* source_provider = "field"
* source_module = "field"
* )
*/
class FieldInstance extends DrupalSqlBase {
@ -21,14 +26,12 @@ class FieldInstance extends DrupalSqlBase {
public function query() {
$query = $this->select('field_config_instance', 'fci')
->fields('fci')
->condition('fci.deleted', 0)
->fields('fc', ['type', 'translatable'])
->condition('fc.active', 1)
->condition('fc.deleted', 0)
->condition('fc.storage_active', 1)
->fields('fc', ['type']);
$query->innerJoin('field_config', 'fc', 'fci.field_id = fc.id');
$query->addField('fc', 'data', 'field_data');
->condition('fc.deleted', 0)
->condition('fci.deleted', 0);
$query->join('field_config', 'fc', 'fci.field_id = fc.id');
// Optionally filter by entity type and bundle.
if (isset($this->configuration['entity_type'])) {
@ -39,22 +42,59 @@ class FieldInstance extends DrupalSqlBase {
}
}
// If the Drupal 7 Title module is enabled, we don't want to migrate the
// fields it provides. The values of those fields will be migrated to the
// base fields they were replacing.
if ($this->moduleExists('title')) {
$title_fields = [
'title_field',
'name_field',
'description_field',
'subject_field',
];
$query->condition('fc.field_name', $title_fields, 'NOT IN');
}
return $query;
}
/**
* {@inheritdoc}
*/
protected function initializeIterator() {
$results = $this->prepareQuery()->execute()->fetchAll();
// Group all instances by their base field.
$instances = [];
foreach ($results as $result) {
$instances[$result['field_id']][] = $result;
}
// Add the array of all instances using the same base field to each row.
$rows = [];
foreach ($results as $result) {
$result['instances'] = $instances[$result['field_id']];
$rows[] = $result;
}
return new \ArrayIterator($rows);
}
/**
* {@inheritdoc}
*/
public function fields() {
return [
'field_name' => $this->t('The machine name of field.'),
'id' => $this->t('The field instance ID.'),
'field_id' => $this->t('The field ID.'),
'field_name' => $this->t('The field name.'),
'entity_type' => $this->t('The entity type.'),
'bundle' => $this->t('The entity bundle.'),
'default_value' => $this->t('Default value'),
'instance_settings' => $this->t('Field instance settings.'),
'widget_settings' => $this->t('Widget settings.'),
'display_settings' => $this->t('Display settings.'),
'field_settings' => $this->t('Field settings.'),
'data' => $this->t('The field instance data.'),
'deleted' => $this->t('Deleted'),
'type' => $this->t('The field type'),
'instances' => $this->t('The field instances.'),
'field_definition' => $this->t('The field definition.'),
];
}
@ -62,46 +102,34 @@ class FieldInstance extends DrupalSqlBase {
* {@inheritdoc}
*/
public function prepareRow(Row $row) {
$data = unserialize($row->getSourceProperty('data'));
$row->setSourceProperty('label', $data['label']);
$row->setSourceProperty('description', $data['description']);
$row->setSourceProperty('required', $data['required']);
$default_value = !empty($data['default_value']) ? $data['default_value'] : [];
if ($data['widget']['type'] == 'email_textfield' && $default_value) {
$default_value[0]['value'] = $default_value[0]['email'];
unset($default_value[0]['email']);
foreach (unserialize($row->getSourceProperty('data')) as $key => $value) {
$row->setSourceProperty($key, $value);
}
$row->setSourceProperty('default_value', $default_value);
// Settings.
$row->setSourceProperty('instance_settings', $data['settings']);
$row->setSourceProperty('widget_settings', $data['widget']);
$row->setSourceProperty('display_settings', $data['display']);
// This is for parity with the d6_field_instance plugin.
$row->setSourceProperty('widget_type', $data['widget']['type']);
$field_data = unserialize($row->getSourceProperty('field_data'));
$row->setSourceProperty('field_settings', $field_data['settings']);
$field_definition = $this->select('field_config', 'fc')
->fields('fc')
->condition('id', $row->getSourceProperty('field_id'))
->execute()
->fetch();
$row->setSourceProperty('field_definition', $field_definition);
$translatable = FALSE;
if ($row->getSourceProperty('entity_type') == 'node') {
$language_content_type_bundle = (int) $this->variableGet('language_content_type_' . $row->getSourceProperty('bundle'), 0);
// language_content_type_[bundle] may be
// - 0: no language support
// - 1: language assignment support
// - 2: node translation support
// - 4: entity translation support
if ($this->variableGet('language_content_type_' . $row->getSourceProperty('bundle'), 0) == 2) {
if ($language_content_type_bundle === 2 || ($language_content_type_bundle === 4 && $row->getSourceProperty('translatable'))) {
$translatable = TRUE;
}
}
else {
// This is not a node entity. Get the translatable value from the source
// field_config table.
$data = unserialize($row->getSourceProperty('field_data'));
$translatable = $data['translatable'];
$field_data = unserialize($field_definition['data']);
$translatable = $field_data['translatable'];
}
$row->setSourceProperty('translatable', $translatable);
@ -128,4 +156,11 @@ class FieldInstance extends DrupalSqlBase {
];
}
/**
* {@inheritdoc}
*/
public function count($refresh = FALSE) {
return $this->initializeIterator()->count();
}
}

View file

@ -2,58 +2,15 @@
namespace Drupal\field\Plugin\migrate\source\d7;
use Drupal\migrate\Row;
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
/**
* The field instance per form display source class.
*
* @MigrateSource(
* id = "d7_field_instance_per_form_display"
* id = "d7_field_instance_per_form_display",
* source_module = "field"
* )
*/
class FieldInstancePerFormDisplay extends DrupalSqlBase {
/**
* {@inheritdoc}
*/
public function query() {
$query = $this->select('field_config_instance', 'fci')
->fields('fci', [
'field_name',
'bundle',
'data',
'entity_type'
])
->fields('fc', [
'type',
'module',
]);
$query->join('field_config', 'fc', 'fci.field_id = fc.id');
return $query;
}
/**
* {@inheritdoc}
*/
public function prepareRow(Row $row) {
$data = unserialize($row->getSourceProperty('data'));
$row->setSourceProperty('widget', $data['widget']);
$row->setSourceProperty('widget_settings', $data['widget']['settings']);
return parent::prepareRow($row);
}
/**
* {@inheritdoc}
*/
public function fields() {
return [
'field_name' => $this->t('The machine name of field.'),
'bundle' => $this->t('Content type where this field is used.'),
'data' => $this->t('Field configuration data.'),
'entity_type' => $this->t('The entity type.'),
];
}
class FieldInstancePerFormDisplay extends FieldInstance {
/**
* {@inheritdoc}

View file

@ -2,69 +2,43 @@
namespace Drupal\field\Plugin\migrate\source\d7;
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
/**
* The field instance per view mode source class.
*
* @MigrateSource(
* id = "d7_field_instance_per_view_mode",
* source_provider = "field"
* source_module = "field"
* )
*/
class FieldInstancePerViewMode extends DrupalSqlBase {
class FieldInstancePerViewMode extends FieldInstance {
/**
* {@inheritdoc}
*/
protected function initializeIterator() {
$instances = parent::initializeIterator();
$rows = [];
$result = $this->prepareQuery()->execute();
foreach ($result as $field_instance) {
$data = unserialize($field_instance['data']);
// We don't need to include the serialized data in the returned rows.
unset($field_instance['data']);
foreach ($data['display'] as $view_mode => $info) {
// Rename type to formatter_type in the info array.
$info['formatter_type'] = $info['type'];
unset($info['type']);
$rows[] = array_merge($field_instance, $info, [
foreach ($instances->getArrayCopy() as $instance) {
$data = unserialize($instance['data']);
foreach ($data['display'] as $view_mode => $formatter) {
$rows[] = array_merge($instance, [
'view_mode' => $view_mode,
'formatter' => $formatter,
]);
}
}
return new \ArrayIterator($rows);
}
/**
* {@inheritdoc}
*/
public function query() {
$query = $this->select('field_config_instance', 'fci')
->fields('fci', ['entity_type', 'bundle', 'field_name', 'data'])
->fields('fc', ['type']);
$query->join('field_config', 'fc', 'fc.field_name = fci.field_name');
return $query;
}
/**
* {@inheritdoc}
*/
public function fields() {
return [
'entity_type' => $this->t('The entity type ID.'),
'bundle' => $this->t('The bundle ID.'),
'field_name' => $this->t('Machine name of the field.'),
return array_merge(parent::fields(), [
'view_mode' => $this->t('The original machine name of the view mode.'),
'label' => $this->t('The display label of the field.'),
'type' => $this->t('The field ID.'),
'formatter_type' => $this->t('The formatter ID.'),
'settings' => $this->t('Array of formatter-specific settings.'),
'module' => $this->t('The module providing the formatter.'),
'weight' => $this->t('Display weight of the field.'),
];
'formatter' => $this->t('The formatter settings.'),
]);
}
/**
@ -87,11 +61,4 @@ class FieldInstancePerViewMode extends DrupalSqlBase {
];
}
/**
* {@inheritdoc}
*/
public function count() {
return $this->initializeIterator()->count();
}
}

View file

@ -2,31 +2,33 @@
namespace Drupal\field\Plugin\migrate\source\d7;
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
/**
* The view mode source class.
*
* @MigrateSource(
* id = "d7_view_mode"
* id = "d7_view_mode",
* source_module = "field"
* )
*/
class ViewMode extends DrupalSqlBase {
class ViewMode extends FieldInstance {
/**
* {@inheritdoc}
*/
protected function initializeIterator() {
$instances = parent::initializeIterator();
$rows = [];
$result = $this->prepareQuery()->execute();
foreach ($result as $field_instance) {
$data = unserialize($field_instance['data']);
foreach ($instances->getArrayCopy() as $instance) {
$data = unserialize($instance['data']);
foreach (array_keys($data['display']) as $view_mode) {
$key = $field_instance['entity_type'] . '.' . $view_mode;
$rows[$key] = [
'entity_type' => $field_instance['entity_type'],
$key = $instance['entity_type'] . '.' . $view_mode;
$rows[$key] = array_merge($instance, [
'view_mode' => $view_mode,
];
]);
}
}
return new \ArrayIterator($rows);
}
@ -34,18 +36,9 @@ class ViewMode extends DrupalSqlBase {
* {@inheritdoc}
*/
public function fields() {
return [
return array_merge(parent::fields(), [
'view_mode' => $this->t('The view mode ID.'),
'entity_type' => $this->t('The entity type ID.'),
];
}
/**
* {@inheritdoc}
*/
public function query() {
return $this->select('field_config_instance', 'fci')
->fields('fci', ['entity_type', 'data']);
]);
}
/**
@ -62,11 +55,4 @@ class ViewMode extends DrupalSqlBase {
];
}
/**
* {@inheritdoc}
*/
public function count() {
return $this->initializeIterator()->count();
}
}

View file

@ -2,7 +2,6 @@
namespace Drupal\field\Tests\EntityReference;
use Drupal\Component\Utility\Unicode;
use Drupal\field\Entity\FieldConfig;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\field_ui\Tests\FieldUiTestTrait;
@ -94,6 +93,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 . ']');
@ -292,7 +293,7 @@ class EntityReferenceAdminTest extends WebTestBase {
$edit = [
'title[0][value]' => 'Example',
'field_test_entity_ref_field[0][target_id]' => 'Test'
'field_test_entity_ref_field[0][target_id]' => 'Test',
];
$this->drupalPostForm('node/add/' . $this->type, $edit, t('Save'));
@ -301,7 +302,7 @@ class EntityReferenceAdminTest extends WebTestBase {
$edit = [
'title[0][value]' => 'Test',
'field_test_entity_ref_field[0][target_id]' => $node1->getTitle()
'field_test_entity_ref_field[0][target_id]' => $node1->getTitle(),
];
$this->drupalPostForm('node/add/' . $this->type, $edit, t('Save'));
@ -314,7 +315,7 @@ class EntityReferenceAdminTest extends WebTestBase {
$edit = [
'title[0][value]' => 'Test',
'field_test_entity_ref_field[0][target_id]' => $node1->getTitle() . ' (' . $node1->id() . ')'
'field_test_entity_ref_field[0][target_id]' => $node1->getTitle() . ' (' . $node1->id() . ')',
];
$this->drupalPostForm('node/add/' . $this->type, $edit, t('Save'));
$this->assertLink($node1->getTitle());
@ -330,6 +331,12 @@ class EntityReferenceAdminTest extends WebTestBase {
$this->drupalPostForm(NULL, $edit, t('Save field settings'));
$this->drupalGet($bundle_path . '/fields/' . $field_path);
$term_name = $this->randomString();
$result = \Drupal::entityQuery('taxonomy_term')
->condition('name', $term_name)
->condition('vid', 'tags')
->accessCheck(FALSE)
->execute();
$this->assertIdentical(0, count($result), "No taxonomy terms exist with the name '$term_name'.");
$edit = [
// This must be set before new entities will be auto-created.
'settings[handler_settings][auto_create]' => 1,
@ -342,8 +349,12 @@ class EntityReferenceAdminTest extends WebTestBase {
];
$this->drupalPostForm(NULL, $edit, t('Save settings'));
// The term should now exist.
$term = taxonomy_term_load_multiple_by_name($term_name, 'tags')[1];
$this->assertIdentical(1, count($term), 'Taxonomy term was auto created when set as field default.');
$result = \Drupal::entityQuery('taxonomy_term')
->condition('name', $term_name)
->condition('vid', 'tags')
->accessCheck(FALSE)
->execute();
$this->assertIdentical(1, count($result), 'Taxonomy term was auto created when set as field default.');
}
/**
@ -412,7 +423,7 @@ class EntityReferenceAdminTest extends WebTestBase {
/** @var \Drupal\taxonomy\Entity\Vocabulary[] $vocabularies */
$vocabularies = [];
for ($i = 0; $i < 2; $i++) {
$vid = Unicode::strtolower($this->randomMachineName());
$vid = mb_strtolower($this->randomMachineName());
$vocabularies[$i] = Vocabulary::create([
'name' => $this->randomString(),
'vid' => $vid,

View file

@ -2,63 +2,18 @@
namespace Drupal\field\Tests\EntityReference;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\Tests\field\Traits\EntityReferenceTestTrait as nonDeprecatedEntityReferenceTestTrait;
/**
* Provides common functionality for the EntityReference test classes.
*
* @deprecated in Drupal 8.6.2 for removal before 9.0.0. Use
* Drupal\Tests\field\Traits\EntityReferenceTestTrait instead.
*
* @see https://www.drupal.org/node/2998888
*/
trait EntityReferenceTestTrait {
/**
* Creates a field of an entity reference field storage on the specified bundle.
*
* @param string $entity_type
* The type of entity the field will be attached to.
* @param string $bundle
* The bundle name of the entity the field will be attached to.
* @param string $field_name
* The name of the field; if it already exists, a new instance of the existing
* field will be created.
* @param string $field_label
* The label of the field.
* @param string $target_entity_type
* The type of the referenced entity.
* @param string $selection_handler
* The selection handler used by this field.
* @param array $selection_handler_settings
* An array of settings supported by the selection handler specified above.
* (e.g. 'target_bundles', 'sort', 'auto_create', etc).
* @param int $cardinality
* The cardinality of the field.
*
* @see \Drupal\Core\Entity\Plugin\EntityReferenceSelection\SelectionBase::buildConfigurationForm()
*/
protected function createEntityReferenceField($entity_type, $bundle, $field_name, $field_label, $target_entity_type, $selection_handler = 'default', $selection_handler_settings = [], $cardinality = 1) {
// Look for or add the specified field to the requested entity bundle.
if (!FieldStorageConfig::loadByName($entity_type, $field_name)) {
FieldStorageConfig::create([
'field_name' => $field_name,
'type' => 'entity_reference',
'entity_type' => $entity_type,
'cardinality' => $cardinality,
'settings' => [
'target_type' => $target_entity_type,
],
])->save();
}
if (!FieldConfig::loadByName($entity_type, $bundle, $field_name)) {
FieldConfig::create([
'field_name' => $field_name,
'entity_type' => $entity_type,
'bundle' => $bundle,
'label' => $field_label,
'settings' => [
'handler' => $selection_handler,
'handler_settings' => $selection_handler_settings,
],
])->save();
}
}
use nonDeprecatedEntityReferenceTestTrait;
}

View file

@ -36,7 +36,7 @@ abstract class FieldTestBase extends WebTestBase {
*
* This function only checks a single column in the field values.
*
* @param EntityInterface $entity
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity to test.
* @param $field_name
* The name of the field to test

View file

@ -1,144 +0,0 @@
<?php
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()]);
}
/**
* Tests field_update_8003().
*
* @see field_update_8003()
*/
public function testFieldUpdate8003() {
// Run updates.
$this->runUpdates();
// Check that the new 'auto_create_bundle' setting is populated correctly.
$field = $this->configFactory->get('field.field.node.article.field_ref_autocreate_2412569');
$handler_settings = $field->get('settings.handler_settings');
$expected_target_bundles = ['tags' => 'tags', 'test' => 'test'];
$this->assertEqual($handler_settings['target_bundles'], $expected_target_bundles);
$this->assertTrue($handler_settings['auto_create']);
$this->assertEqual($handler_settings['auto_create_bundle'], 'tags');
}
/**
* 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

@ -2,6 +2,8 @@
namespace Drupal\field\Tests\Views;
@trigger_error(__NAMESPACE__ . '\FieldTestBase is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\field\Functional\Views\FieldTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
use Drupal\field\Entity\FieldConfig;
use Drupal\node\Entity\NodeType;
use Drupal\views\Tests\ViewTestBase;
@ -17,6 +19,11 @@ use Drupal\field\Entity\FieldStorageConfig;
* - Use basic fields and make sure that the full wanted object is built.
* - Use relationships between different entity types, for example node and
* the node author(user).
*
* @deprecated in Drupal 8.6.0. Will be removed before Drupal 9.0.0. Use
* \Drupal\Tests\field\Functional\Views\FieldTestBase instead.
*
* @see https://www.drupal.org/node/2989020
*/
abstract class FieldTestBase extends ViewTestBase {
@ -42,8 +49,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([

View file

@ -0,0 +1,26 @@
<?php
/**
* @file
* Provides necessary database additions for testing
* field_post_update_remove_handler_submit_setting()
*/
use Drupal\Core\Database\Database;
$connection = Database::getConnection();
$config = unserialize($connection->select('config', 'c')
->fields('c', ['data'])
->condition('collection', '')
->condition('name', 'field.field.node.article.field_tags')
->execute()
->fetchField());
$config['settings']['handler_submit'] = 'Change handler';
$connection->update('config')
->fields(['data' => serialize($config)])
->condition('collection', '')
->condition('name', 'field.field.node.article.field_tags')
->execute();

View file

@ -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();

View file

@ -66,7 +66,7 @@ $connection->update('key_value')
->condition('collection', 'entity.definitions.installed')
->condition('name', 'node.field_storage_definitions')
->fields([
'value' => serialize($installed)
'value' => serialize($installed),
])
->execute();

View file

@ -5,4 +5,4 @@ core: 8.x
package: Testing
version: VERSION
dependencies:
- text
- drupal:text

View file

@ -55,6 +55,18 @@ 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.settings.test_field_widget_multilingual:
type: field.widget.settings.test_field_widget
label: 'Test multiple field widget settings: multilingual'
field.widget.third_party.color:
type: mapping
label: 'Field test entity display color module third party settings'

View file

@ -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';
}
}
}
/**

View file

@ -5,4 +5,4 @@ core: 8.x
package: Testing
version: VERSION
dependencies:
- entity_test
- drupal:entity_test

View file

@ -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,20 +101,54 @@ 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']) {
drupal_set_message('From hook_field_widget_form_alter(): Default form is true.');
\Drupal::messenger()
->addStatus('From hook_field_widget_form_alter(): Default form is true.');
}
}
/**
* 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::messenger()->addStatus("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.";
}
}
}
@ -128,7 +163,6 @@ function field_test_query_efq_table_prefixing_test_alter(&$query) {
$query->join('entity_test', 'et2', '%alias.id = entity_test.id');
}
/**
* Implements hook_query_TAG_alter() for tag 'efq_metadata_test'.
*
@ -151,15 +185,18 @@ function field_test_entity_extra_field_info_alter(&$info) {
* Implements hook_entity_bundle_field_info_alter().
*/
function field_test_entity_bundle_field_info_alter(&$fields, EntityTypeInterface $entity_type, $bundle) {
if (($field_name = \Drupal::state()->get('field_test_set_constraint', FALSE)) && $entity_type->id() == 'entity_test' && $bundle == 'entity_test' && !empty($fields[$field_name])) {
if (($field_name = \Drupal::state()->get('field_test_constraint', FALSE)) && $entity_type->id() == 'entity_test' && $bundle == 'entity_test' && !empty($fields[$field_name])) {
// Set a property constraint using
// \Drupal\Core\Field\FieldConfigInterface::setPropertyConstraints().
$fields[$field_name]->setPropertyConstraints('value', [
'Range' => [
'min' => 0,
'max' => 32,
'TestField' => [
'value' => -2,
'message' => t('%name does not accept the value @value.', ['%name' => $field_name, '@value' => -2]),
],
]);
}
if (($field_name = \Drupal::state()->get('field_test_add_constraint', FALSE)) && $entity_type->id() == 'entity_test' && $bundle == 'entity_test' && !empty($fields[$field_name])) {
// Add a property constraint using
// \Drupal\Core\Field\FieldConfigInterface::addPropertyConstraints().
$fields[$field_name]->addPropertyConstraints('value', [
'Range' => [
'min' => 0,
@ -168,3 +205,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',
];
}
}

View file

@ -1,9 +1,9 @@
<?php
namespace Drupal\field\Tests;
namespace Drupal\field_test;
/**
* Helper class for \Drupal\field\Tests\FieldDefaultValueCallbackTest.
* Helper class for \Drupal\Tests\field\Functional\FieldDefaultValueCallbackTest.
*/
class FieldDefaultValueCallbackProvider {

View file

@ -10,6 +10,8 @@ use Drupal\Core\Entity\Entity\EntityFormDisplay;
/**
* Provides a form for field_test routes.
*
* @internal
*/
class NestedEntityTestForm extends FormBase {
@ -40,14 +42,14 @@ class NestedEntityTestForm extends FormBase {
'#tree' => TRUE,
'#parents' => ['entity_2'],
'#weight' => 50,
'#attributes' => ['class' => ['entity-2']]
'#attributes' => ['class' => ['entity-2']],
];
$form_display_2->buildForm($entity_2, $form['entity_2'], $form_state);
if ($entity_2 instanceof EntityChangedInterface) {
// Changed must be sent to the client, for later overwrite error checking.
// @see Drupal\field\Tests\NestedFormTest::testNestedEntityFormEntityLevelValidation()
// @see \Drupal\Tests\field\Functional\NestedFormTest::testNestedEntityFormEntityLevelValidation()
$form['entity_2']['changed'] = [
'#type' => 'hidden',
'#default_value' => $entity_1->getChangedTime(),
@ -80,7 +82,7 @@ class NestedEntityTestForm extends FormBase {
// Extract the values of fields that are not rendered through widgets, by
// simply copying from top-level form values. This leaves the fields that
// are not being edited within this form untouched.
// @see Drupal\field\Tests\NestedFormTest::testNestedEntityFormEntityLevelValidation()
// @see \Drupal\Tests\field\Functional\NestedFormTest::testNestedEntityFormEntityLevelValidation()
foreach ($form_state->getValues()['entity_2'] as $name => $values) {
if ($entity_2->hasField($name) && !isset($extracted[$name])) {
$entity_2->set($name, $values);
@ -90,7 +92,7 @@ class NestedEntityTestForm extends FormBase {
}
/**
* {@inheritdoc]
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
/** @var \Drupal\Core\Entity\EntityInterface $entity_1 */
@ -101,7 +103,7 @@ class NestedEntityTestForm extends FormBase {
$entity_2 = $form_state->get('entity_2');
$entity_2->save();
drupal_set_message($this->t('test_entities @id_1 and @id_2 have been updated.', ['@id_1' => $entity_1->id(), '@id_2' => $entity_2->id()]));
$this->messenger()->addStatus($this->t('test_entities @id_1 and @id_2 have been updated.', ['@id_1' => $entity_1->id(), '@id_2' => $entity_2->id()]));
}
}

View file

@ -1,11 +1,11 @@
<?php
namespace Drupal\field_test\Plugin\Field\FieldFormatter;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterBase;
/**
* Plugin implementation of the 'field_test_applicable' formatter.
*

View file

@ -120,7 +120,7 @@ class TestItem extends FieldItemBase {
'TestField' => [
'value' => -1,
'message' => t('%name does not accept the value @value.', ['%name' => $this->getFieldDefinition()->getLabel(), '@value' => -1]),
]
],
],
]);

View file

@ -4,7 +4,6 @@ namespace Drupal\field_test\Plugin\Field\FieldType;
use Drupal\Core\Field\FieldDefinitionInterface;
/**
* Defines the 'test_field_with_dependencies' entity field item.
*

View file

@ -29,7 +29,7 @@ class TestItemWithPreconfiguredOptions extends TestItem implements Preconfigured
'field_storage_config' => [
'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
'settings' => [
'test_field_storage_setting' => 'preconfigured_storage_setting'
'test_field_storage_setting' => 'preconfigured_storage_setting',
],
],
'field_config' => [

View file

@ -0,0 +1,30 @@
<?php
namespace Drupal\field_test\Plugin\Field\FieldWidget;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Form\FormStateInterface;
/**
* Plugin implementation of the 'test_field_widget_multilingual' widget.
*
* @FieldWidget(
* id = "test_field_widget_multilingual",
* label = @Translation("Test widget - multilingual"),
* field_types = {
* "test_field",
* },
* )
*/
class TestFieldWidgetMultilingual extends TestFieldWidget {
/**
* {@inheritdoc}
*/
public function form(FieldItemListInterface $items, array &$form, FormStateInterface $form_state, $get_delta = NULL) {
$elements = parent::form($items, $form, $form_state, $get_delta);
$elements['#multilingual'] = TRUE;
return $elements;
}
}

View file

@ -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 {
}

View file

@ -5,4 +5,4 @@ core: 8.x
package: Testing
version: VERSION
dependencies:
- field
- drupal:field

View file

@ -5,4 +5,4 @@ package: Testing
version: VERSION
core: 8.x
dependencies:
- views
- drupal:views

View file

@ -5,5 +5,5 @@ core: 8.x
package: Testing
version: VERSION
dependencies:
- entity_test
- field_test
- drupal:entity_test
- drupal:field_test

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,9 @@
name: 'Field Timestamp Test'
type: module
description: 'Support module for the Timestamp field item test.'
core: 8.x
package: Testing
version: VERSION
dependencies:
- drupal:entity_test
- drupal:field

View file

@ -1,19 +1,18 @@
<?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.
@ -64,7 +63,7 @@ class BooleanFieldTest extends WebTestBase {
$label = $this->randomMachineName();
// Create a field with settings to validate.
$field_name = Unicode::strtolower($this->randomMachineName());
$field_name = mb_strtolower($this->randomMachineName());
$this->fieldStorage = FieldStorageConfig::create([
'field_name' => $field_name,
'entity_type' => 'entity_test',
@ -108,15 +107,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.
@ -125,7 +122,7 @@ class BooleanFieldTest extends WebTestBase {
'type' => 'boolean_checkbox',
'settings' => [
'display_label' => FALSE,
]
],
])
->save();
@ -150,16 +147,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 +164,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 +223,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 +234,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]));
}

View file

@ -1,19 +1,17 @@
<?php
namespace Drupal\field\Tests\Boolean;
namespace Drupal\Tests\field\Functional\Boolean;
use Drupal\Component\Utility\Unicode;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\simpletest\WebTestBase;
use Drupal\Tests\BrowserTestBase;
/**
* Tests the Boolean field formatter settings.
*
* @group field
*/
class BooleanFormatterSettingsTest extends WebTestBase {
class BooleanFormatterSettingsTest extends BrowserTestBase {
/**
* Modules to enable.
@ -43,14 +41,14 @@ class BooleanFormatterSettingsTest extends WebTestBase {
parent::setUp();
// Create a content type. Use Node because it has Field UI pages that work.
$type_name = Unicode::strtolower($this->randomMachineName(8)) . '_test';
$type_name = mb_strtolower($this->randomMachineName(8)) . '_test';
$type = $this->drupalCreateContentType(['name' => $type_name, 'type' => $type_name]);
$this->bundle = $type->id();
$admin_user = $this->drupalCreateUser(['access content', 'administer content types', 'administer node fields', 'administer node display', 'bypass node access', 'administer nodes']);
$this->drupalLogin($admin_user);
$this->fieldName = Unicode::strtolower($this->randomMachineName(8));
$this->fieldName = mb_strtolower($this->randomMachineName(8));
$field_storage = FieldStorageConfig::create([
'field_name' => $this->fieldName,
@ -90,10 +88,6 @@ class BooleanFormatterSettingsTest extends WebTestBase {
'Custom',
];
// Define what the "default" option should look like, depending on the
// field settings.
$default = 'Field settings (@on / @off)';
// For several different values of the field settings, test that the
// options, including default, are shown correctly.
$settings = [
@ -102,6 +96,7 @@ class BooleanFormatterSettingsTest extends WebTestBase {
['TRUE', 'FALSE'],
];
$assert_session = $this->assertSession();
foreach ($settings as $values) {
// Set up the field settings.
$this->drupalGet('admin/structure/types/manage/' . $this->bundle . '/fields/node.' . $this->bundle . '.' . $this->fieldName);
@ -112,18 +107,20 @@ class BooleanFormatterSettingsTest extends WebTestBase {
// Open the Manage Display page and trigger the field settings form.
$this->drupalGet('admin/structure/types/manage/' . $this->bundle . '/display');
$this->drupalPostAjaxForm(NULL, [], $this->fieldName . '_settings_edit');
$this->drupalPostForm(NULL, [], $this->fieldName . '_settings_edit');
// Test that the settings options are present in the correct format.
foreach ($options as $string) {
$this->assertText($string);
$assert_session->pageTextContains($string);
}
$this->assertText(SafeMarkup::format($default, ['@on' => $values[0], '@off' => $values[1]]));
}
$assert_session->pageTextContains(t('Field settings (@on_label / @off_label)', ['@on_label' => $values[0], '@off_label' => $values[1]]));
foreach ($settings as $values) {
// Test that the settings summary are present in the correct format.
$this->drupalGet('admin/structure/types/manage/' . $this->bundle . '/display');
$result = $this->xpath('//div[contains(@class, :class) and contains(text(), :text)]', [':class' => 'field-plugin-summary', ':text' => 'Display: TRUE / FALSE']);
$result = $this->xpath('//div[contains(@class, :class) and contains(text(), :text)]', [
':class' => 'field-plugin-summary',
':text' => (string) t('Display: @true_label / @false_label', ['@true_label' => $values[0], '@false_label' => $values[1]]),
]);
$this->assertEqual(count($result), 1, "Boolean formatter settings summary exist.");
}
}

View file

@ -1,19 +1,18 @@
<?php
namespace Drupal\field\Tests\Email;
namespace Drupal\Tests\field\Functional\Email;
use Drupal\Component\Utility\Unicode;
use Drupal\entity_test\Entity\EntityTest;
use Drupal\field\Entity\FieldConfig;
use Drupal\simpletest\WebTestBase;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\Tests\BrowserTestBase;
/**
* Tests email field functionality.
*
* @group field
*/
class EmailFieldTest extends WebTestBase {
class EmailFieldTest extends BrowserTestBase {
/**
* Modules to enable.
@ -51,7 +50,7 @@ class EmailFieldTest extends WebTestBase {
*/
public function testEmailField() {
// Create a field with settings to validate.
$field_name = Unicode::strtolower($this->randomMachineName());
$field_name = mb_strtolower($this->randomMachineName());
$this->fieldStorage = FieldStorageConfig::create([
'field_name' => $field_name,
'entity_type' => 'entity_test',
@ -91,7 +90,7 @@ class EmailFieldTest extends WebTestBase {
"{$field_name}[0][value]" => $value,
];
$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]));
$this->assertRaw($value);
@ -100,8 +99,8 @@ class EmailFieldTest extends WebTestBase {
$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->assertLinkByHref('mailto:test@example.com');
$rendered_content = (string) \Drupal::service('renderer')->renderRoot($content);
$this->assertContains('href="mailto:test@example.com"', $rendered_content);
}
}

View file

@ -2,11 +2,10 @@
namespace Drupal\Tests\field\Functional\EntityReference;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\Tests\BrowserTestBase;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\Tests\field\Traits\EntityReferenceTestTrait;
use Drupal\taxonomy\Entity\Vocabulary;
use Drupal\node\Entity\Node;
use Drupal\field\Entity\FieldStorageConfig;
@ -145,7 +144,7 @@ class EntityReferenceAutoCreateTest extends BrowserTestBase {
/** @var \Drupal\taxonomy\Entity\Vocabulary[] $vocabularies */
$vocabularies = [];
for ($i = 0; $i < 2; $i++) {
$vid = Unicode::strtolower($this->randomMachineName());
$vid = mb_strtolower($this->randomMachineName());
$vocabularies[$i] = Vocabulary::create([
'name' => $this->randomMachineName(),
'vid' => $vid,
@ -156,7 +155,7 @@ class EntityReferenceAutoCreateTest extends BrowserTestBase {
// Create a taxonomy term entity reference field that saves the auto-created
// taxonomy terms in the second vocabulary from the two that were configured
// as targets.
$field_name = Unicode::strtolower($this->randomMachineName());
$field_name = mb_strtolower($this->randomMachineName());
$handler_settings = [
'target_bundles' => [
$vocabularies[0]->id() => $vocabularies[0]->id(),
@ -213,17 +212,17 @@ class EntityReferenceAutoCreateTest extends BrowserTestBase {
// a way to catch and assert user-triggered errors.
// Test the case when the field config settings are inconsistent.
//unset($handler_settings['auto_create_bundle']);
//$field_config->setSetting('handler_settings', $handler_settings);
//$field_config->save();
// unset($handler_settings['auto_create_bundle']);
// $field_config->setSetting('handler_settings', $handler_settings);
// $field_config->save();
//
//$this->drupalGet('node/add/' . $this->referencingType);
//$error_message = sprintf(
// $this->drupalGet('node/add/' . $this->referencingType);
// $error_message = sprintf(
// "Create referenced entities if they don't already exist option is enabled but a specific destination bundle is not set. You should re-visit and fix the settings of the '%s' (%s) field.",
// $field_config->getLabel(),
// $field_config->getName()
//);
//$this->assertErrorLogged($error_message);
// );
// $this->assertErrorLogged($error_message);
}
}

View file

@ -2,7 +2,6 @@
namespace Drupal\Tests\field\Functional\EntityReference;
use Drupal\Component\Utility\Unicode;
use Drupal\Tests\SchemaCheckTestTrait;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
@ -51,7 +50,7 @@ class EntityReferenceFieldDefaultValueTest extends BrowserTestBase {
// Create a node to be referenced.
$referenced_node = $this->drupalCreateNode(['type' => 'referenced_content']);
$field_name = Unicode::strtolower($this->randomMachineName());
$field_name = mb_strtolower($this->randomMachineName());
$field_storage = FieldStorageConfig::create([
'field_name' => $field_name,
'entity_type' => 'node',
@ -114,7 +113,7 @@ class EntityReferenceFieldDefaultValueTest extends BrowserTestBase {
$referenced_node_type = $this->drupalCreateContentType(['type' => 'referenced_config_to_delete']);
$referenced_node_type2 = $this->drupalCreateContentType(['type' => 'referenced_config_to_preserve']);
$field_name = Unicode::strtolower($this->randomMachineName());
$field_name = mb_strtolower($this->randomMachineName());
$field_storage = FieldStorageConfig::create([
'field_name' => $field_name,
'entity_type' => 'node',

View file

@ -302,7 +302,6 @@ class EntityReferenceFieldTranslatedReferenceViewTest extends BrowserTestBase {
return $node;
}
/**
* Create the referenced entity.
*/

View file

@ -1,18 +1,21 @@
<?php
namespace Drupal\field\Tests\EntityReference;
namespace Drupal\Tests\field\Functional\EntityReference;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\simpletest\WebTestBase;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\Tests\BrowserTestBase;
use Drupal\Tests\TestFileCreationTrait;
/**
* Tests an autocomplete widget with file upload.
*
* @group entity_reference
*/
class EntityReferenceFileUploadTest extends WebTestBase {
class EntityReferenceFileUploadTest extends BrowserTestBase {
use TestFileCreationTrait;
public static $modules = ['entity_reference', 'node', 'file'];
@ -77,13 +80,12 @@ class EntityReferenceFileUploadTest extends WebTestBase {
],
])->save();
// Create a file field.
$file_field_name = 'file_field';
$field_storage = FieldStorageConfig::create([
'field_name' => $file_field_name,
'entity_type' => 'node',
'type' => 'file'
'type' => 'file',
]);
$field_storage->save();
FieldConfig::create([
@ -114,8 +116,8 @@ class EntityReferenceFileUploadTest extends WebTestBase {
$user1 = $this->drupalCreateUser(['access content', "create $this->referencingType content"]);
$this->drupalLogin($user1);
$test_file = current($this->drupalGetTestFiles('text'));
$edit['files[file_field_0]'] = drupal_realpath($test_file->uri);
$test_file = current($this->getTestFiles('text'));
$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 = [

View file

@ -2,12 +2,12 @@
namespace Drupal\Tests\field\Functional\EntityReference;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\config\Tests\AssertConfigEntityImportTrait;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\entity_test\Entity\EntityTest;
use Drupal\field\Entity\FieldConfig;
use Drupal\Tests\BrowserTestBase;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\Tests\config\Traits\AssertConfigEntityImportTrait;
use Drupal\Tests\field\Traits\EntityReferenceTestTrait;
/**
* Tests various Entity reference UI components.
@ -149,7 +149,7 @@ class EntityReferenceIntegrationTest extends BrowserTestBase {
// Ensure the configuration has the expected dependency on the entity that
// is being used a default value.
$field = FieldConfig::loadByName($this->entityType, $this->bundle, $this->fieldName);
$this->assertTrue(in_array($referenced_entities[0]->getConfigDependencyName(), $field->getDependencies()[$key]), SafeMarkup::format('Expected @type dependency @name found', ['@type' => $key, '@name' => $referenced_entities[0]->getConfigDependencyName()]));
$this->assertTrue(in_array($referenced_entities[0]->getConfigDependencyName(), $field->getDependencies()[$key]), new FormattableMarkup('Expected @type dependency @name found', ['@type' => $key, '@name' => $referenced_entities[0]->getConfigDependencyName()]));
// Ensure that the field can be imported without change even after the
// default value deleted.
$referenced_entities[0]->delete();
@ -163,7 +163,7 @@ class EntityReferenceIntegrationTest extends BrowserTestBase {
$field = FieldConfig::loadByName($this->entityType, $this->bundle, $this->fieldName);
$field->save();
$dependencies = $field->getDependencies();
$this->assertFalse(isset($dependencies[$key]) && in_array($referenced_entities[0]->getConfigDependencyName(), $dependencies[$key]), SafeMarkup::format('@type dependency @name does not exist.', ['@type' => $key, '@name' => $referenced_entities[0]->getConfigDependencyName()]));
$this->assertFalse(isset($dependencies[$key]) && in_array($referenced_entities[0]->getConfigDependencyName(), $dependencies[$key]), new FormattableMarkup('@type dependency @name does not exist.', ['@type' => $key, '@name' => $referenced_entities[0]->getConfigDependencyName()]));
}
}
@ -197,9 +197,10 @@ class EntityReferenceIntegrationTest extends BrowserTestBase {
* An array of entity objects.
*/
protected function getTestEntities() {
$config_entity_1 = entity_create('config_test', ['id' => $this->randomMachineName(), 'label' => $this->randomMachineName()]);
$storage = \Drupal::entityTypeManager()->getStorage('config_test');
$config_entity_1 = $storage->create(['id' => $this->randomMachineName(), 'label' => $this->randomMachineName()]);
$config_entity_1->save();
$config_entity_2 = entity_create('config_test', ['id' => $this->randomMachineName(), 'label' => $this->randomMachineName()]);
$config_entity_2 = $storage->create(['id' => $this->randomMachineName(), 'label' => $this->randomMachineName()]);
$config_entity_2->save();
$content_entity_1 = EntityTest::create(['name' => $this->randomMachineName()]);

View file

@ -5,7 +5,7 @@ namespace Drupal\Tests\field\Functional\EntityReference;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\Core\Entity\Entity\EntityViewDisplay;
use Drupal\Tests\BrowserTestBase;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\Tests\field\Traits\EntityReferenceTestTrait;
/**
* Tests possible XSS security issues in entity references.
@ -60,9 +60,9 @@ class EntityReferenceXSSTest extends BrowserTestBase {
$edit = [
'title[0][value]' => $this->randomString(),
'entity_reference_test' => $referenced_node->id()
'entity_reference_test' => $referenced_node->id(),
];
$this->drupalPostForm(NULL, $edit, 'Save and publish');
$this->drupalPostForm(NULL, $edit, 'Save');
$this->assertEscaped($referenced_node->getTitle());
// Test the options_buttons type.

View file

@ -127,7 +127,7 @@ class SelectionTest extends BrowserTestBase {
'table' => 'users_field_data',
'field' => 'uid',
'relationship' => 'test_relationship',
]
],
]);
// Set view to distinct so only one row per node is returned.

View file

@ -1,17 +1,17 @@
<?php
namespace Drupal\field\Tests;
namespace Drupal\Tests\field\Functional;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\simpletest\WebTestBase;
use Drupal\Tests\BrowserTestBase;
/**
* Tests the default value callback.
*
* @group field
*/
class FieldDefaultValueCallbackTest extends WebTestBase {
class FieldDefaultValueCallbackTest extends BrowserTestBase {
/**
* Modules to enable.
@ -81,7 +81,7 @@ class FieldDefaultValueCallbackTest extends WebTestBase {
// Set a default value callback instead, and the default field form should
// not be visible.
$field_config->setDefaultValueCallback('\Drupal\field\Tests\FieldDefaultValueCallbackProvider::calculateDefaultValue')->save();
$field_config->setDefaultValueCallback('\Drupal\field_test\FieldDefaultValueCallbackProvider::calculateDefaultValue')->save();
$this->drupalGet('/admin/structure/types/manage/article/fields/node.article.field_test');
$this->assertNoFieldByName('default_value_input[field_test][0][value]', 'Calculated default value', 'The default field form is not visible when a callback is defined.');
}

View file

@ -14,7 +14,7 @@ class FieldHelpTest extends BrowserTestBase {
/**
* Modules to enable.
*
* @var array.
* @var array
*/
public static $modules = ['field', 'help'];

View file

@ -1,6 +1,6 @@
<?php
namespace Drupal\field\Tests;
namespace Drupal\Tests\field\Functional;
use Drupal\entity_test\Entity\EntityTest;
use Drupal\field\Entity\FieldConfig;

View file

@ -33,7 +33,7 @@ abstract class FieldTestBase extends BrowserTestBase {
*
* This function only checks a single column in the field values.
*
* @param EntityInterface $entity
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity to test.
* @param $field_name
* The name of the field to test

View file

@ -1,6 +1,6 @@
<?php
namespace Drupal\field\Tests;
namespace Drupal\Tests\field\Functional;
use Drupal\Component\Utility\Html;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
@ -113,10 +113,13 @@ 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 = [
"{$field_name}[0][value]" => -1
"{$field_name}[0][value]" => -1,
];
$this->drupalPostForm(NULL, $edit, t('Save'));
$this->assertRaw(t('%name does not accept the value -1.', ['%name' => $this->field['label']]), 'Field validation fails with invalid input.');
@ -128,7 +131,7 @@ class FormTest extends FieldTestBase {
"{$field_name}[0][value]" => $value,
];
$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]), 'Entity was created');
$entity = EntityTest::load($id);
@ -153,7 +156,7 @@ class FormTest extends FieldTestBase {
// Empty the field.
$value = '';
$edit = [
"{$field_name}[0][value]" => $value
"{$field_name}[0][value]" => $value,
];
$this->drupalPostForm('entity_test/manage/' . $id . '/edit', $edit, t('Save'));
$this->assertText(t('entity_test @id has been updated.', ['@id' => $id]), 'Entity was updated');
@ -187,7 +190,7 @@ class FormTest extends FieldTestBase {
"{$field_name}[0][value]" => '',
];
$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]), 'Entity was created.');
$entity = EntityTest::load($id);
@ -216,7 +219,7 @@ class FormTest extends FieldTestBase {
"{$field_name}[0][value]" => $value,
];
$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]), 'Entity was created');
$entity = EntityTest::load($id);
@ -297,7 +300,7 @@ class FormTest extends FieldTestBase {
// Submit the form and create the entity.
$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]), 'Entity was created');
$entity = EntityTest::load($id);
@ -389,62 +392,6 @@ class FormTest extends FieldTestBase {
$this->assertNoField("{$field_name}[2][value]", 'No extraneous widget is displayed');
}
public function testFieldFormJSAddMore() {
$field_storage = $this->fieldStorageUnlimited;
$field_name = $field_storage['field_name'];
$this->field['field_name'] = $field_name;
FieldStorageConfig::create($field_storage)->save();
FieldConfig::create($this->field)->save();
entity_get_form_display($this->field['entity_type'], $this->field['bundle'], 'default')
->setComponent($field_name)
->save();
// Display creation form -> 1 widget.
$this->drupalGet('entity_test/add');
// Press 'add more' button a couple times -> 3 widgets.
// drupalPostAjaxForm() will not work iteratively, so we add those through
// non-JS submission.
$this->drupalPostForm(NULL, [], t('Add another item'));
$this->drupalPostForm(NULL, [], t('Add another item'));
// Prepare values and weights.
$count = 3;
$delta_range = $count - 1;
$values = $weights = $pattern = $expected_values = $edit = [];
for ($delta = 0; $delta <= $delta_range; $delta++) {
// Assign unique random values and weights.
do {
$value = mt_rand(1, 127);
} while (in_array($value, $values));
do {
$weight = mt_rand(-$delta_range, $delta_range);
} while (in_array($weight, $weights));
$edit["{$field_name}[$delta][value]"] = $value;
$edit["{$field_name}[$delta][_weight]"] = $weight;
// We'll need three slightly different formats to check the values.
$values[$delta] = $value;
$weights[$delta] = $weight;
$field_values[$weight]['value'] = (string) $value;
$pattern[$weight] = "<input [^>]*value=\"$value\" [^>]*";
}
// Press 'add more' button through Ajax, and place the expected HTML result
// as the tested content.
$commands = $this->drupalPostAjaxForm(NULL, $edit, $field_name . '_add_more');
$this->setRawContent($commands[2]['data']);
for ($delta = 0; $delta <= $delta_range; $delta++) {
$this->assertFieldByName("{$field_name}[$delta][value]", $values[$delta], "Widget $delta is displayed and has the right value");
$this->assertFieldByName("{$field_name}[$delta][_weight]", $weights[$delta], "Widget $delta has the right weight");
}
ksort($pattern);
$pattern = implode('.*', array_values($pattern));
$this->assertPattern("|$pattern|s", 'Widgets are displayed in the correct order');
$this->assertFieldByName("{$field_name}[$delta][value]", '', "New widget is displayed");
$this->assertFieldByName("{$field_name}[$delta][_weight]", $delta, "New widget has the right weight");
$this->assertNoField("{$field_name}[" . ($delta + 1) . '][value]', 'No extraneous widget is displayed');
}
/**
* Tests widgets handling multiple values.
*/
@ -471,7 +418,7 @@ class FormTest extends FieldTestBase {
$field_name => '1, 2, 3',
];
$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];
// Check that the values were saved.
@ -551,7 +498,7 @@ class FormTest extends FieldTestBase {
"{$field_name}[0][value]" => 1,
];
$this->drupalPostForm(NULL, $edit, t('Save'));
preg_match("|$entity_type/manage/(\d+)|", $this->url, $match);
preg_match("|$entity_type/manage/(\d+)|", $this->getUrl(), $match);
$id = $match[1];
// Check that the default value was saved.
@ -607,7 +554,7 @@ class FormTest extends FieldTestBase {
// the field that uses the hidden widget.
$this->assertNoField("{$field_name}[0][value]", 'The field does not appear in the form');
$this->drupalPostForm(NULL, [], t('Save'));
preg_match('|' . $entity_type . '/manage/(\d+)|', $this->url, $match);
preg_match('|' . $entity_type . '/manage/(\d+)|', $this->getUrl(), $match);
$id = $match[1];
$this->assertText(t('entity_test_rev @id has been created.', ['@id' => $id]), 'Entity was created');
$storage = $this->container->get('entity_type.manager')
@ -690,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");
}
}
}

View file

@ -0,0 +1,30 @@
<?php
namespace Drupal\Tests\field\Functional\Hal;
use Drupal\Tests\field\Functional\Rest\FieldConfigResourceTestBase;
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
/**
* @group hal
*/
class FieldConfigHalJsonAnonTest extends FieldConfigResourceTestBase {
use AnonResourceTestTrait;
/**
* {@inheritdoc}
*/
public static $modules = ['hal'];
/**
* {@inheritdoc}
*/
protected static $format = 'hal_json';
/**
* {@inheritdoc}
*/
protected static $mimeType = 'application/hal+json';
}

View file

@ -0,0 +1,35 @@
<?php
namespace Drupal\Tests\field\Functional\Hal;
use Drupal\Tests\field\Functional\Rest\FieldConfigResourceTestBase;
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
/**
* @group hal
*/
class FieldConfigHalJsonBasicAuthTest extends FieldConfigResourceTestBase {
use BasicAuthResourceTestTrait;
/**
* {@inheritdoc}
*/
public static $modules = ['hal', 'basic_auth'];
/**
* {@inheritdoc}
*/
protected static $format = 'hal_json';
/**
* {@inheritdoc}
*/
protected static $mimeType = 'application/hal+json';
/**
* {@inheritdoc}
*/
protected static $auth = 'basic_auth';
}

View file

@ -0,0 +1,35 @@
<?php
namespace Drupal\Tests\field\Functional\Hal;
use Drupal\Tests\field\Functional\Rest\FieldConfigResourceTestBase;
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
/**
* @group hal
*/
class FieldConfigHalJsonCookieTest extends FieldConfigResourceTestBase {
use CookieResourceTestTrait;
/**
* {@inheritdoc}
*/
public static $modules = ['hal'];
/**
* {@inheritdoc}
*/
protected static $format = 'hal_json';
/**
* {@inheritdoc}
*/
protected static $mimeType = 'application/hal+json';
/**
* {@inheritdoc}
*/
protected static $auth = 'cookie';
}

View file

@ -0,0 +1,30 @@
<?php
namespace Drupal\Tests\field\Functional\Hal;
use Drupal\Tests\field\Functional\Rest\FieldStorageConfigResourceTestBase;
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
/**
* @group hal
*/
class FieldStorageConfigHalJsonAnonTest extends FieldStorageConfigResourceTestBase {
use AnonResourceTestTrait;
/**
* {@inheritdoc}
*/
public static $modules = ['hal'];
/**
* {@inheritdoc}
*/
protected static $format = 'hal_json';
/**
* {@inheritdoc}
*/
protected static $mimeType = 'application/hal+json';
}

View file

@ -0,0 +1,35 @@
<?php
namespace Drupal\Tests\field\Functional\Hal;
use Drupal\Tests\field\Functional\Rest\FieldStorageConfigResourceTestBase;
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
/**
* @group hal
*/
class FieldStorageConfigHalJsonBasicAuthTest extends FieldStorageConfigResourceTestBase {
use BasicAuthResourceTestTrait;
/**
* {@inheritdoc}
*/
public static $modules = ['hal', 'basic_auth'];
/**
* {@inheritdoc}
*/
protected static $format = 'hal_json';
/**
* {@inheritdoc}
*/
protected static $mimeType = 'application/hal+json';
/**
* {@inheritdoc}
*/
protected static $auth = 'basic_auth';
}

View file

@ -0,0 +1,35 @@
<?php
namespace Drupal\Tests\field\Functional\Hal;
use Drupal\Tests\field\Functional\Rest\FieldStorageConfigResourceTestBase;
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
/**
* @group hal
*/
class FieldStorageConfigHalJsonCookieTest extends FieldStorageConfigResourceTestBase {
use CookieResourceTestTrait;
/**
* {@inheritdoc}
*/
public static $modules = ['hal'];
/**
* {@inheritdoc}
*/
protected static $format = 'hal_json';
/**
* {@inheritdoc}
*/
protected static $mimeType = 'application/hal+json';
/**
* {@inheritdoc}
*/
protected static $auth = 'cookie';
}

View file

@ -1,6 +1,7 @@
<?php
namespace Drupal\field\Tests;
namespace Drupal\Tests\field\Functional;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
@ -138,12 +139,10 @@ class NestedFormTest extends FieldTestBase {
$this->assertFieldValues($entity_1, 'field_unlimited', [3, 2]);
$this->assertFieldValues($entity_2, 'field_unlimited', [13, 12]);
// Test the 'add more' buttons. Only Ajax submission is tested, because
// the two 'add more' buttons present in the form have the same #value,
// which confuses drupalPostForm().
// Test the 'add more' buttons.
// 'Add more' button in the first entity:
$this->drupalGet('test-entity/nested/1/2');
$this->drupalPostAjaxForm(NULL, [], 'field_unlimited_add_more');
$this->drupalPostForm(NULL, [], 'field_unlimited_add_more');
$this->assertFieldByName('field_unlimited[0][value]', 3, 'Entity 1: field_unlimited value 0 appears correctly is the form.');
$this->assertFieldByName('field_unlimited[1][value]', 2, 'Entity 1: field_unlimited value 1 appears correctly is the form.');
$this->assertFieldByName('field_unlimited[2][value]', '', 'Entity 1: field_unlimited value 2 appears correctly is the form.');
@ -154,7 +153,7 @@ class NestedFormTest extends FieldTestBase {
'entity_2[field_unlimited][1][value]' => 14,
'entity_2[field_unlimited][2][value]' => 15,
];
$this->drupalPostAjaxForm(NULL, $edit, 'entity_2_field_unlimited_add_more');
$this->drupalPostForm(NULL, $edit, 'entity_2_field_unlimited_add_more');
$this->assertFieldByName('entity_2[field_unlimited][0][value]', 13, 'Entity 2: field_unlimited value 0 appears correctly is the form.');
$this->assertFieldByName('entity_2[field_unlimited][1][value]', 14, 'Entity 2: field_unlimited value 1 appears correctly is the form.');
$this->assertFieldByName('entity_2[field_unlimited][2][value]', 15, 'Entity 2: field_unlimited value 2 appears correctly is the form.');
@ -179,13 +178,17 @@ class NestedFormTest extends FieldTestBase {
$entity_2 = $storage->create();
$entity_2->save();
$page = $this->getSession()->getPage();
$assert_session = $this->assertSession();
// Display the 'combined form'.
$this->drupalGet("test-entity-constraints/nested/{$entity_1->id()}/{$entity_2->id()}");
$this->assertFieldByName('entity_2[changed]', 0, 'Entity 2: changed value appears correctly in the form.');
$assert_session->hiddenFieldValueEquals('entity_2[changed]', REQUEST_TIME);
// Submit the form and check that the entities are updated accordingly.
$edit = ['entity_2[changed]' => REQUEST_TIME - 86400];
$this->drupalPostForm(NULL, $edit, t('Save'));
$assert_session->hiddenFieldExists('entity_2[changed]')
->setValue(REQUEST_TIME - 86400);
$page->pressButton(t('Save'));
$elements = $this->cssSelect('.entity-2.error');
$this->assertEqual(1, count($elements), 'The whole nested entity form has been correctly flagged with an error class.');

View file

@ -1,19 +1,17 @@
<?php
namespace Drupal\field\Tests\Number;
namespace Drupal\Tests\field\Functional\Number;
use Drupal\Component\Utility\Unicode;
use Drupal\field\Entity\FieldConfig;
use Drupal\node\Entity\Node;
use Drupal\simpletest\WebTestBase;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\Tests\BrowserTestBase;
/**
* Tests the creation of numeric fields.
*
* @group field
*/
class NumberFieldTest extends WebTestBase {
class NumberFieldTest extends BrowserTestBase {
/**
* Modules to enable.
@ -40,14 +38,12 @@ class NumberFieldTest extends WebTestBase {
*/
public function testNumberDecimalField() {
// Create a field with settings to validate.
$field_name = Unicode::strtolower($this->randomMachineName());
$field_name = mb_strtolower($this->randomMachineName());
FieldStorageConfig::create([
'field_name' => $field_name,
'entity_type' => 'entity_test',
'type' => 'decimal',
'settings' => [
'precision' => 8, 'scale' => 4,
]
'settings' => ['precision' => 8, 'scale' => 4],
])->save();
FieldConfig::create([
'field_name' => $field_name,
@ -59,7 +55,7 @@ class NumberFieldTest extends WebTestBase {
->setComponent($field_name, [
'type' => 'number',
'settings' => [
'placeholder' => '0.00'
'placeholder' => '0.00',
],
])
->save();
@ -80,7 +76,7 @@ class NumberFieldTest extends WebTestBase {
"{$field_name}[0][value]" => $value,
];
$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]), 'Entity was created');
$this->assertRaw($value, 'Value is displayed.');
@ -130,7 +126,7 @@ class NumberFieldTest extends WebTestBase {
$maximum = rand(2000, 4000);
// Create a field with settings to validate.
$field_name = Unicode::strtolower($this->randomMachineName());
$field_name = mb_strtolower($this->randomMachineName());
$storage = FieldStorageConfig::create([
'field_name' => $field_name,
'entity_type' => 'entity_test',
@ -143,15 +139,17 @@ class NumberFieldTest extends WebTestBase {
'entity_type' => 'entity_test',
'bundle' => 'entity_test',
'settings' => [
'min' => $minimum, 'max' => $maximum, 'prefix' => 'ThePrefix',
]
'min' => $minimum,
'max' => $maximum,
'prefix' => 'ThePrefix',
],
])->save();
entity_get_form_display('entity_test', 'entity_test', 'default')
->setComponent($field_name, [
'type' => 'number',
'settings' => [
'placeholder' => '4'
'placeholder' => '4',
],
])
->save();
@ -170,12 +168,12 @@ class NumberFieldTest extends WebTestBase {
'value' => [
'type' => 'int',
'unsigned' => '',
'size' => 'normal'
'size' => 'normal',
],
],
'unique keys' => [],
'indexes' => [],
'foreign keys' => []
'foreign keys' => [],
];
$this->assertEqual($storage->getSchema(), $expected);
@ -190,7 +188,7 @@ class NumberFieldTest extends WebTestBase {
"{$field_name}[0][value]" => $value,
];
$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]), 'Entity was created');
@ -239,7 +237,7 @@ class NumberFieldTest extends WebTestBase {
"{$field_name}[0][value]" => $valid_entry,
];
$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]), 'Entity was created');
$this->assertRaw($valid_entry, 'Value is displayed.');
@ -261,7 +259,7 @@ class NumberFieldTest extends WebTestBase {
"{$field_name}[0][value]" => $integer_value,
];
$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]), 'Entity was created');
$this->drupalGet('entity_test/' . $id);
@ -273,7 +271,7 @@ class NumberFieldTest extends WebTestBase {
*/
public function testNumberFloatField() {
// Create a field with settings to validate.
$field_name = Unicode::strtolower($this->randomMachineName());
$field_name = mb_strtolower($this->randomMachineName());
FieldStorageConfig::create([
'field_name' => $field_name,
'entity_type' => 'entity_test',
@ -290,7 +288,7 @@ class NumberFieldTest extends WebTestBase {
->setComponent($field_name, [
'type' => 'number',
'settings' => [
'placeholder' => '0.00'
'placeholder' => '0.00',
],
])
->save();
@ -312,7 +310,7 @@ class NumberFieldTest extends WebTestBase {
"{$field_name}[0][value]" => $value,
];
$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]), 'Entity was created');
@ -358,143 +356,12 @@ class NumberFieldTest extends WebTestBase {
}
}
/**
* Test default formatter behavior
*/
public function testNumberFormatter() {
$type = Unicode::strtolower($this->randomMachineName());
$float_field = Unicode::strtolower($this->randomMachineName());
$integer_field = Unicode::strtolower($this->randomMachineName());
$thousand_separators = ['', '.', ',', ' ', chr(8201), "'"];
$decimal_separators = ['.', ','];
$prefix = $this->randomMachineName();
$suffix = $this->randomMachineName();
$random_float = rand(0, pow(10, 6));
$random_integer = rand(0, pow(10, 6));
// Create a content type containing float and integer fields.
$this->drupalCreateContentType(['type' => $type]);
FieldStorageConfig::create([
'field_name' => $float_field,
'entity_type' => 'node',
'type' => 'float',
])->save();
FieldStorageConfig::create([
'field_name' => $integer_field,
'entity_type' => 'node',
'type' => 'integer',
])->save();
FieldConfig::create([
'field_name' => $float_field,
'entity_type' => 'node',
'bundle' => $type,
'settings' => [
'prefix' => $prefix,
'suffix' => $suffix
],
])->save();
FieldConfig::create([
'field_name' => $integer_field,
'entity_type' => 'node',
'bundle' => $type,
'settings' => [
'prefix' => $prefix,
'suffix' => $suffix
],
])->save();
entity_get_form_display('node', $type, 'default')
->setComponent($float_field, [
'type' => 'number',
'settings' => [
'placeholder' => '0.00'
],
])
->setComponent($integer_field, [
'type' => 'number',
'settings' => [
'placeholder' => '0.00'
],
])
->save();
entity_get_display('node', $type, 'default')
->setComponent($float_field, [
'type' => 'number_decimal',
])
->setComponent($integer_field, [
'type' => 'number_unformatted',
])
->save();
// Create a node to test formatters.
$node = Node::create([
'type' => $type,
'title' => $this->randomMachineName(),
$float_field => ['value' => $random_float],
$integer_field => ['value' => $random_integer],
]);
$node->save();
// Go to manage display page.
$this->drupalGet("admin/structure/types/manage/$type/display");
// Configure number_decimal formatter for the 'float' field type.
$thousand_separator = $thousand_separators[array_rand($thousand_separators)];
$decimal_separator = $decimal_separators[array_rand($decimal_separators)];
$scale = rand(0, 10);
$this->drupalPostAjaxForm(NULL, [], "${float_field}_settings_edit");
$edit = [
"fields[${float_field}][settings_edit_form][settings][prefix_suffix]" => TRUE,
"fields[${float_field}][settings_edit_form][settings][scale]" => $scale,
"fields[${float_field}][settings_edit_form][settings][decimal_separator]" => $decimal_separator,
"fields[${float_field}][settings_edit_form][settings][thousand_separator]" => $thousand_separator,
];
$this->drupalPostAjaxForm(NULL, $edit, "${float_field}_plugin_settings_update");
$this->drupalPostForm(NULL, [], t('Save'));
// Check number_decimal and number_unformatted formatters behavior.
$this->drupalGet('node/' . $node->id());
$float_formatted = number_format($random_float, $scale, $decimal_separator, $thousand_separator);
$this->assertRaw("$prefix$float_formatted$suffix", 'Prefix and suffix added');
$this->assertRaw((string) $random_integer);
// Configure the number_decimal formatter.
entity_get_display('node', $type, 'default')
->setComponent($integer_field, [
'type' => 'number_integer',
])
->save();
$this->drupalGet("admin/structure/types/manage/$type/display");
$thousand_separator = $thousand_separators[array_rand($thousand_separators)];
$this->drupalPostAjaxForm(NULL, [], "${integer_field}_settings_edit");
$edit = [
"fields[${integer_field}][settings_edit_form][settings][prefix_suffix]" => FALSE,
"fields[${integer_field}][settings_edit_form][settings][thousand_separator]" => $thousand_separator,
];
$this->drupalPostAjaxForm(NULL, $edit, "${integer_field}_plugin_settings_update");
$this->drupalPostForm(NULL, [], t('Save'));
// Check number_integer formatter behavior.
$this->drupalGet('node/' . $node->id());
$integer_formatted = number_format($random_integer, 0, '', $thousand_separator);
$this->assertRaw($integer_formatted, 'Random integer formatted');
}
/**
* Tests setting the minimum value of a float field through the interface.
*/
public function testCreateNumberFloatField() {
// Create a float field.
$field_name = Unicode::strtolower($this->randomMachineName());
$field_name = mb_strtolower($this->randomMachineName());
FieldStorageConfig::create([
'field_name' => $field_name,
'entity_type' => 'entity_test',
@ -519,7 +386,7 @@ class NumberFieldTest extends WebTestBase {
*/
public function testCreateNumberDecimalField() {
// Create a decimal field.
$field_name = Unicode::strtolower($this->randomMachineName());
$field_name = mb_strtolower($this->randomMachineName());
FieldStorageConfig::create([
'field_name' => $field_name,
'entity_type' => 'entity_test',

View file

@ -0,0 +1,24 @@
<?php
namespace Drupal\Tests\field\Functional\Rest;
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
/**
* @group rest
*/
class FieldConfigJsonAnonTest extends FieldConfigResourceTestBase {
use AnonResourceTestTrait;
/**
* {@inheritdoc}
*/
protected static $format = 'json';
/**
* {@inheritdoc}
*/
protected static $mimeType = 'application/json';
}

View file

@ -0,0 +1,34 @@
<?php
namespace Drupal\Tests\field\Functional\Rest;
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
/**
* @group rest
*/
class FieldConfigJsonBasicAuthTest extends FieldConfigResourceTestBase {
use BasicAuthResourceTestTrait;
/**
* {@inheritdoc}
*/
public static $modules = ['basic_auth'];
/**
* {@inheritdoc}
*/
protected static $format = 'json';
/**
* {@inheritdoc}
*/
protected static $mimeType = 'application/json';
/**
* {@inheritdoc}
*/
protected static $auth = 'basic_auth';
}

View file

@ -0,0 +1,29 @@
<?php
namespace Drupal\Tests\field\Functional\Rest;
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
/**
* @group rest
*/
class FieldConfigJsonCookieTest extends FieldConfigResourceTestBase {
use CookieResourceTestTrait;
/**
* {@inheritdoc}
*/
protected static $format = 'json';
/**
* {@inheritdoc}
*/
protected static $mimeType = 'application/json';
/**
* {@inheritdoc}
*/
protected static $auth = 'cookie';
}

View file

@ -0,0 +1,119 @@
<?php
namespace Drupal\Tests\field\Functional\Rest;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\node\Entity\NodeType;
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
abstract class FieldConfigResourceTestBase extends EntityResourceTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['field', 'node'];
/**
* {@inheritdoc}
*/
protected static $entityTypeId = 'field_config';
/**
* @var \Drupal\field\FieldConfigInterface
*/
protected $entity;
/**
* {@inheritdoc}
*/
protected function setUpAuthorization($method) {
$this->grantPermissionsToTestedRole(['administer node fields']);
}
/**
* {@inheritdoc}
*/
protected function createEntity() {
$camelids = NodeType::create([
'name' => 'Camelids',
'type' => 'camelids',
]);
$camelids->save();
$field_storage = FieldStorageConfig::create([
'field_name' => 'field_llama',
'entity_type' => 'node',
'type' => 'text',
]);
$field_storage->save();
$entity = FieldConfig::create([
'field_storage' => $field_storage,
'bundle' => 'camelids',
]);
$entity->save();
return $entity;
}
/**
* {@inheritdoc}
*/
protected function getExpectedNormalizedEntity() {
return [
'bundle' => 'camelids',
'default_value' => [],
'default_value_callback' => '',
'dependencies' => [
'config' => [
'field.storage.node.field_llama',
'node.type.camelids',
],
'module' => [
'text',
],
],
'description' => '',
'entity_type' => 'node',
'field_name' => 'field_llama',
'field_type' => 'text',
'id' => 'node.camelids.field_llama',
'label' => 'field_llama',
'langcode' => 'en',
'required' => FALSE,
'settings' => [],
'status' => TRUE,
'translatable' => TRUE,
'uuid' => $this->entity->uuid(),
];
}
/**
* {@inheritdoc}
*/
protected function getNormalizedPostEntity() {
// @todo Update in https://www.drupal.org/node/2300677.
}
/**
* {@inheritdoc}
*/
protected function getExpectedCacheContexts() {
return [
'user.permissions',
];
}
/**
* {@inheritdoc}
*/
protected function getExpectedUnauthorizedAccessMessage($method) {
if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) {
return parent::getExpectedUnauthorizedAccessMessage($method);
}
return "The 'administer node fields' permission is required.";
}
}

View file

@ -0,0 +1,26 @@
<?php
namespace Drupal\Tests\field\Functional\Rest;
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
/**
* @group rest
*/
class FieldConfigXmlAnonTest extends FieldConfigResourceTestBase {
use AnonResourceTestTrait;
use XmlEntityNormalizationQuirksTrait;
/**
* {@inheritdoc}
*/
protected static $format = 'xml';
/**
* {@inheritdoc}
*/
protected static $mimeType = 'text/xml; charset=UTF-8';
}

View file

@ -0,0 +1,36 @@
<?php
namespace Drupal\Tests\field\Functional\Rest;
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
/**
* @group rest
*/
class FieldConfigXmlBasicAuthTest extends FieldConfigResourceTestBase {
use BasicAuthResourceTestTrait;
use XmlEntityNormalizationQuirksTrait;
/**
* {@inheritdoc}
*/
public static $modules = ['basic_auth'];
/**
* {@inheritdoc}
*/
protected static $format = 'xml';
/**
* {@inheritdoc}
*/
protected static $mimeType = 'text/xml; charset=UTF-8';
/**
* {@inheritdoc}
*/
protected static $auth = 'basic_auth';
}

View file

@ -0,0 +1,31 @@
<?php
namespace Drupal\Tests\field\Functional\Rest;
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
/**
* @group rest
*/
class FieldConfigXmlCookieTest extends FieldConfigResourceTestBase {
use CookieResourceTestTrait;
use XmlEntityNormalizationQuirksTrait;
/**
* {@inheritdoc}
*/
protected static $format = 'xml';
/**
* {@inheritdoc}
*/
protected static $mimeType = 'text/xml; charset=UTF-8';
/**
* {@inheritdoc}
*/
protected static $auth = 'cookie';
}

View file

@ -0,0 +1,24 @@
<?php
namespace Drupal\Tests\field\Functional\Rest;
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
/**
* @group rest
*/
class FieldStorageConfigJsonAnonTest extends FieldStorageConfigResourceTestBase {
use AnonResourceTestTrait;
/**
* {@inheritdoc}
*/
protected static $format = 'json';
/**
* {@inheritdoc}
*/
protected static $mimeType = 'application/json';
}

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