upgrades core to 8.4.2

This commit is contained in:
Bachir Soussi Chiadmi
2017-11-14 16:09:54 +01:00
parent bd60eff9b3
commit c2b4e25be4
3504 changed files with 140306 additions and 38684 deletions
@@ -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;
@@ -189,13 +190,19 @@ class FieldConfig extends FieldConfigBase implements FieldConfigInterface {
*/
public static function preDelete(EntityStorageInterface $storage, array $fields) {
$state = \Drupal::state();
$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') ?: [];
/** @var \Drupal\field\FieldConfigInterface $field */
foreach ($fields as $field) {
if (!$field->deleted) {
// Only mark a field for purging if there is data. Otherwise, just remove
// it.
$target_entity_storage = $entity_type_manager->getStorage($field->getTargetEntityTypeId());
if (!$field->deleted && $target_entity_storage instanceof FieldableEntityStorageInterface && $target_entity_storage->countFieldData($field->getFieldStorageDefinition(), TRUE)) {
$config = $field->toArray();
$config['deleted'] = TRUE;
$config['field_storage_uuid'] = $field->getFieldStorageDefinition()->uuid();
@@ -6,6 +6,7 @@ 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;
@@ -409,8 +410,12 @@ class FieldStorageConfig extends ConfigEntityBase implements FieldStorageConfigI
// 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') ?: [];
/** @var \Drupal\field\FieldStorageConfigInterface $field_storage */
foreach ($field_storages as $field_storage) {
if (!$field_storage->deleted) {
// Only mark a field for purging if there is data. Otherwise, just remove
// it.
$target_entity_storage = \Drupal::entityTypeManager()->getStorage($field_storage->getTargetEntityTypeId());
if (!$field_storage->deleted && $target_entity_storage instanceof FieldableEntityStorageInterface && $target_entity_storage->countFieldData($field_storage, TRUE)) {
$config = $field_storage->toArray();
$config['deleted'] = TRUE;
$config['bundles'] = $field_storage->getBundles();
@@ -628,7 +633,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;
}
/**
@@ -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 exists or is not callable.');
}
return call_user_func_array([$plugin_instance, $method], [$row]);
}
}
@@ -19,6 +19,14 @@ 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 ?: [];
// 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']);
}
$default = [];
@@ -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'];
@@ -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 {
@@ -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 {
@@ -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 {
@@ -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 {
@@ -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"
* )
*/
class Field extends DrupalSqlBase {
@@ -23,8 +29,9 @@ 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');
return $query;
@@ -35,13 +42,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 +66,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);
}
@@ -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'])
->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'])) {
@@ -42,19 +45,43 @@ class FieldInstance extends DrupalSqlBase {
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,29 +89,16 @@ 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') {
@@ -100,8 +114,8 @@ class FieldInstance extends DrupalSqlBase {
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 +142,11 @@ class FieldInstance extends DrupalSqlBase {
];
}
/**
* {@inheritdoc}
*/
public function count() {
return $this->initializeIterator()->count();
}
}
@@ -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}
@@ -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();
}
}
@@ -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();
}
}
-56
View File
@@ -389,62 +389,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.
*/
@@ -1,6 +1,7 @@
<?php
namespace Drupal\field\Tests;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
@@ -45,9 +45,7 @@ class NumberFieldTest extends WebTestBase {
'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,
@@ -143,8 +141,10 @@ 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')
@@ -57,7 +57,7 @@ class FieldUITest extends FieldTestBase {
// Tests the available formatter options.
$result = $this->xpath('//select[@id=:id]/option', [':id' => 'edit-options-type']);
$options = array_map(function($item) {
$options = array_map(function ($item) {
return (string) $item->attributes()->value[0];
}, $result);
// @todo Replace this sort by assertArray once it's in.
@@ -111,7 +111,7 @@ class FieldUITest extends FieldTestBase {
// Test the click sort column options.
// Tests the available formatter options.
$result = $this->xpath('//select[@id=:id]/option', [':id' => 'edit-options-click-sort-column']);
$options = array_map(function($item) {
$options = array_map(function ($item) {
return (string) $item->attributes()->value[0];
}, $result);
sort($options, SORT_STRING);