Update core 8.3.0

This commit is contained in:
Rob Davies 2017-04-13 15:53:35 +01:00
parent da7a7918f8
commit cd7a898e66
6144 changed files with 132297 additions and 87747 deletions

View file

@ -14,6 +14,7 @@ content:
title:
type: string_textfield
weight: -5
region: content
settings:
size: 60
placeholder: ''
@ -21,6 +22,7 @@ content:
uid:
type: entity_reference_autocomplete
weight: 5
region: content
settings:
match_operator: CONTAINS
size: 60
@ -29,6 +31,7 @@ content:
created:
type: datetime_timestamp
weight: 10
region: content
settings: { }
third_party_settings: { }
promote:
@ -36,16 +39,19 @@ content:
settings:
display_label: true
weight: 15
region: content
third_party_settings: { }
sticky:
type: boolean_checkbox
settings:
display_label: true
weight: 16
region: content
third_party_settings: { }
body:
type: text_textarea_with_summary
weight: 26
region: content
settings:
rows: 9
summary_rows: 3

View file

@ -14,10 +14,12 @@ mode: default
content:
links:
weight: 100
region: content
body:
label: hidden
type: text_default
weight: 101
region: content
settings: { }
third_party_settings: { }
hidden:

View file

@ -15,10 +15,12 @@ mode: teaser
content:
links:
weight: 100
region: content
body:
label: hidden
type: text_summary_or_trimmed
weight: 101
region: content
settings:
trim_length: 600
third_party_settings: { }

View file

@ -14,18 +14,18 @@ use Drupal\Core\Field\FieldStorageDefinitionInterface;
* @see options_allowed_values()
*/
function options_test_allowed_values_callback(FieldStorageDefinitionInterface $definition, FieldableEntityInterface $entity = NULL) {
$values = array(
'Group 1' => array(
$values = [
'Group 1' => [
0 => 'Zero',
),
],
1 => 'One',
'Group 2' => array(
'Group 2' => [
2 => 'Some <script>dangerous</script> & unescaped <strong>markup</strong>',
),
'More <script>dangerous</script> markup' => array(
],
'More <script>dangerous</script> markup' => [
3 => 'Three',
),
);
],
];
return $values;
}
@ -41,15 +41,15 @@ function options_test_allowed_values_callback(FieldStorageDefinitionInterface $d
* @see options_allowed_values()
*/
function options_test_dynamic_values_callback(FieldStorageDefinitionInterface $definition, FieldableEntityInterface $entity = NULL, &$cacheable = NULL) {
$values = array();
$values = [];
if (isset($entity)) {
$cacheable = FALSE;
$values = array(
$values = [
$entity->label(),
$entity->url(),
$entity->uuid(),
$entity->bundle(),
);
];
}
// We need the values of the entity as keys.
return array_combine($values, $values);

View file

@ -0,0 +1,34 @@
<?php
namespace Drupal\Tests\options\Functional;
/**
* Tests the options allowed values api.
*
* @group options
*/
class OptionsDynamicValuesApiTest extends OptionsDynamicValuesTestBase {
/**
* Tests options_allowed_values().
*
* @see options_test_dynamic_values_callback()
*/
public function testOptionsAllowedValues() {
// Test allowed values without passed $items.
$values = options_allowed_values($this->fieldStorage);
$this->assertEqual([], $values);
$values = options_allowed_values($this->fieldStorage, $this->entity);
$expected_values = [
$this->entity->label(),
$this->entity->url(),
$this->entity->uuid(),
$this->entity->bundle(),
];
$expected_values = array_combine($expected_values, $expected_values);
$this->assertEqual($expected_values, $values);
}
}

View file

@ -0,0 +1,79 @@
<?php
namespace Drupal\Tests\options\Functional;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Tests\FieldTestBase;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\entity_test\Entity\EntityTestRev;
/**
* Base class for testing allowed values of options fields.
*/
abstract class OptionsDynamicValuesTestBase extends FieldTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['options', 'entity_test', 'options_test'];
/**
* The created entity.
*
* @var \Drupal\Core\Entity\Entity
*/
protected $entity;
/**
* The field storage.
*
* @var \Drupal\Core\Field\FieldStorageDefinitionInterface
*/
protected $fieldStorage;
protected function setUp() {
parent::setUp();
$field_name = 'test_options';
$this->fieldStorage = FieldStorageConfig::create([
'field_name' => $field_name,
'entity_type' => 'entity_test_rev',
'type' => 'list_string',
'cardinality' => 1,
'settings' => [
'allowed_values_function' => 'options_test_dynamic_values_callback',
],
]);
$this->fieldStorage->save();
$this->field = FieldConfig::create([
'field_name' => $field_name,
'entity_type' => 'entity_test_rev',
'bundle' => 'entity_test_rev',
'required' => TRUE,
])->save();
entity_get_form_display('entity_test_rev', 'entity_test_rev', 'default')
->setComponent($field_name, [
'type' => 'options_select',
])
->save();
// Create an entity and prepare test data that will be used by
// options_test_dynamic_values_callback().
$values = [
'user_id' => mt_rand(1, 10),
'name' => $this->randomMachineName(),
];
$this->entity = EntityTestRev::create($values);
$this->entity->save();
$this->test = [
'label' => $this->entity->label(),
'uuid' => $this->entity->uuid(),
'bundle' => $this->entity->bundle(),
'uri' => $this->entity->url(),
];
}
}

View file

@ -0,0 +1,30 @@
<?php
namespace Drupal\Tests\options\Functional;
/**
* Tests the Options field allowed values function.
*
* @group options
*/
class OptionsDynamicValuesValidationTest extends OptionsDynamicValuesTestBase {
/**
* Test that allowed values function gets the entity.
*/
public function testDynamicAllowedValues() {
// Verify that validation passes against every value we had.
foreach ($this->test as $key => $value) {
$this->entity->test_options->value = $value;
$violations = $this->entity->test_options->validate();
$this->assertEqual(count($violations), 0, "$key is a valid value");
}
// Now verify that validation does not pass against anything else.
foreach ($this->test as $key => $value) {
$this->entity->test_options->value = is_numeric($value) ? (100 - $value) : ('X' . $value);
$violations = $this->entity->test_options->validate();
$this->assertEqual(count($violations), 1, "$key is not a valid value");
}
}
}

View file

@ -0,0 +1,355 @@
<?php
namespace Drupal\Tests\options\Functional;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\field\Tests\FieldTestBase;
/**
* Tests the Options field UI functionality.
*
* @group options
*/
class OptionsFieldUITest extends FieldTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['node', 'options', 'field_test', 'taxonomy', 'field_ui'];
/**
* The name of the created content type.
*
* @var string
*/
protected $typeName;
/**
* Machine name of the created content type.
*
* @var string
*/
protected $type;
/**
* Name of the option field.
*
* @var string
*/
protected $fieldName;
/**
* Admin path to manage field storage settings.
*
* @var string
*/
protected $adminPath;
protected function setUp() {
parent::setUp();
// Create test user.
$admin_user = $this->drupalCreateUser(['access content', 'administer taxonomy', 'access administration pages', 'administer site configuration', 'administer content types', 'administer nodes', 'bypass node access', 'administer node fields', 'administer node display']);
$this->drupalLogin($admin_user);
// Create content type, with underscores.
$this->typeName = 'test_' . strtolower($this->randomMachineName());
$type = $this->drupalCreateContentType(['name' => $this->typeName, 'type' => $this->typeName]);
$this->type = $type->id();
}
/**
* Options (integer) : test 'allowed values' input.
*/
public function testOptionsAllowedValuesInteger() {
$this->fieldName = 'field_options_integer';
$this->createOptionsField('list_integer');
// Flat list of textual values.
$string = "Zero\nOne";
$array = ['0' => 'Zero', '1' => 'One'];
$this->assertAllowedValuesInput($string, $array, 'Unkeyed lists are accepted.');
// Explicit integer keys.
$string = "0|Zero\n2|Two";
$array = ['0' => 'Zero', '2' => 'Two'];
$this->assertAllowedValuesInput($string, $array, 'Integer keys are accepted.');
// Check that values can be added and removed.
$string = "0|Zero\n1|One";
$array = ['0' => 'Zero', '1' => 'One'];
$this->assertAllowedValuesInput($string, $array, 'Values can be added and removed.');
// Non-integer keys.
$this->assertAllowedValuesInput("1.1|One", 'keys must be integers', 'Non integer keys are rejected.');
$this->assertAllowedValuesInput("abc|abc", 'keys must be integers', 'Non integer keys are rejected.');
// Mixed list of keyed and unkeyed values.
$this->assertAllowedValuesInput("Zero\n1|One", 'invalid input', 'Mixed lists are rejected.');
// Create a node with actual data for the field.
$settings = [
'type' => $this->type,
$this->fieldName => [['value' => 1]],
];
$node = $this->drupalCreateNode($settings);
// Check that a flat list of values is rejected once the field has data.
$this->assertAllowedValuesInput( "Zero\nOne", 'invalid input', 'Unkeyed lists are rejected once the field has data.');
// Check that values can be added but values in use cannot be removed.
$string = "0|Zero\n1|One\n2|Two";
$array = ['0' => 'Zero', '1' => 'One', '2' => 'Two'];
$this->assertAllowedValuesInput($string, $array, 'Values can be added.');
$string = "0|Zero\n1|One";
$array = ['0' => 'Zero', '1' => 'One'];
$this->assertAllowedValuesInput($string, $array, 'Values not in use can be removed.');
$this->assertAllowedValuesInput("0|Zero", 'some values are being removed while currently in use', 'Values in use cannot be removed.');
// Delete the node, remove the value.
$node->delete();
$string = "0|Zero";
$array = ['0' => 'Zero'];
$this->assertAllowedValuesInput($string, $array, 'Values not in use can be removed.');
// Check that the same key can only be used once.
$string = "0|Zero\n0|One";
$array = ['0' => 'One'];
$this->assertAllowedValuesInput($string, $array, 'Same value cannot be used multiple times.');
}
/**
* Options (float) : test 'allowed values' input.
*/
public function testOptionsAllowedValuesFloat() {
$this->fieldName = 'field_options_float';
$this->createOptionsField('list_float');
// Flat list of textual values.
$string = "Zero\nOne";
$array = ['0' => 'Zero', '1' => 'One'];
$this->assertAllowedValuesInput($string, $array, 'Unkeyed lists are accepted.');
// Explicit numeric keys.
$string = "0|Zero\n.5|Point five";
$array = ['0' => 'Zero', '0.5' => 'Point five'];
$this->assertAllowedValuesInput($string, $array, 'Integer keys are accepted.');
// Check that values can be added and removed.
$string = "0|Zero\n.5|Point five\n1.0|One";
$array = ['0' => 'Zero', '0.5' => 'Point five', '1' => 'One'];
$this->assertAllowedValuesInput($string, $array, 'Values can be added and removed.');
// Non-numeric keys.
$this->assertAllowedValuesInput("abc|abc\n", 'each key must be a valid integer or decimal', 'Non numeric keys are rejected.');
// Mixed list of keyed and unkeyed values.
$this->assertAllowedValuesInput("Zero\n1|One\n", 'invalid input', 'Mixed lists are rejected.');
// Create a node with actual data for the field.
$settings = [
'type' => $this->type,
$this->fieldName => [['value' => .5]],
];
$node = $this->drupalCreateNode($settings);
// Check that a flat list of values is rejected once the field has data.
$this->assertAllowedValuesInput("Zero\nOne", 'invalid input', 'Unkeyed lists are rejected once the field has data.');
// Check that values can be added but values in use cannot be removed.
$string = "0|Zero\n.5|Point five\n2|Two";
$array = ['0' => 'Zero', '0.5' => 'Point five', '2' => 'Two'];
$this->assertAllowedValuesInput($string, $array, 'Values can be added.');
$string = "0|Zero\n.5|Point five";
$array = ['0' => 'Zero', '0.5' => 'Point five'];
$this->assertAllowedValuesInput($string, $array, 'Values not in use can be removed.');
$this->assertAllowedValuesInput("0|Zero", 'some values are being removed while currently in use', 'Values in use cannot be removed.');
// Delete the node, remove the value.
$node->delete();
$string = "0|Zero";
$array = ['0' => 'Zero'];
$this->assertAllowedValuesInput($string, $array, 'Values not in use can be removed.');
// Check that the same key can only be used once.
$string = "0.5|Point five\n0.5|Half";
$array = ['0.5' => 'Half'];
$this->assertAllowedValuesInput($string, $array, 'Same value cannot be used multiple times.');
// Check that different forms of the same float value cannot be used.
$string = "0|Zero\n.5|Point five\n0.5|Half";
$array = ['0' => 'Zero', '0.5' => 'Half'];
$this->assertAllowedValuesInput($string, $array, 'Different forms of the same value cannot be used.');
}
/**
* Options (text) : test 'allowed values' input.
*/
public function testOptionsAllowedValuesText() {
$this->fieldName = 'field_options_text';
$this->createOptionsField('list_string');
// Flat list of textual values.
$string = "Zero\nOne";
$array = ['Zero' => 'Zero', 'One' => 'One'];
$this->assertAllowedValuesInput($string, $array, 'Unkeyed lists are accepted.');
// Explicit keys.
$string = "zero|Zero\none|One";
$array = ['zero' => 'Zero', 'one' => 'One'];
$this->assertAllowedValuesInput($string, $array, 'Explicit keys are accepted.');
// Check that values can be added and removed.
$string = "zero|Zero\ntwo|Two";
$array = ['zero' => 'Zero', 'two' => 'Two'];
$this->assertAllowedValuesInput($string, $array, 'Values can be added and removed.');
// Mixed list of keyed and unkeyed values.
$string = "zero|Zero\nOne\n";
$array = ['zero' => 'Zero', 'One' => 'One'];
$this->assertAllowedValuesInput($string, $array, 'Mixed lists are accepted.');
// Overly long keys.
$this->assertAllowedValuesInput("zero|Zero\n" . $this->randomMachineName(256) . "|One", 'each key must be a string at most 255 characters long', 'Overly long keys are rejected.');
// Create a node with actual data for the field.
$settings = [
'type' => $this->type,
$this->fieldName => [['value' => 'One']],
];
$node = $this->drupalCreateNode($settings);
// Check that flat lists of values are still accepted once the field has
// data.
$string = "Zero\nOne";
$array = ['Zero' => 'Zero', 'One' => 'One'];
$this->assertAllowedValuesInput($string, $array, 'Unkeyed lists are still accepted once the field has data.');
// Check that values can be added but values in use cannot be removed.
$string = "Zero\nOne\nTwo";
$array = ['Zero' => 'Zero', 'One' => 'One', 'Two' => 'Two'];
$this->assertAllowedValuesInput($string, $array, 'Values can be added.');
$string = "Zero\nOne";
$array = ['Zero' => 'Zero', 'One' => 'One'];
$this->assertAllowedValuesInput($string, $array, 'Values not in use can be removed.');
$this->assertAllowedValuesInput("Zero", 'some values are being removed while currently in use', 'Values in use cannot be removed.');
// Delete the node, remove the value.
$node->delete();
$string = "Zero";
$array = ['Zero' => 'Zero'];
$this->assertAllowedValuesInput($string, $array, 'Values not in use can be removed.');
// Check that string values with dots can be used.
$string = "Zero\nexample.com|Example";
$array = ['Zero' => 'Zero', 'example.com' => 'Example'];
$this->assertAllowedValuesInput($string, $array, 'String value with dot is supported.');
// Check that the same key can only be used once.
$string = "zero|Zero\nzero|One";
$array = ['zero' => 'One'];
$this->assertAllowedValuesInput($string, $array, 'Same value cannot be used multiple times.');
}
/**
* Options (text) : test 'trimmed values' input.
*/
public function testOptionsTrimmedValuesText() {
$this->fieldName = 'field_options_trimmed_text';
$this->createOptionsField('list_string');
// Explicit keys.
$string = "zero |Zero\none | One";
$array = ['zero' => 'Zero', 'one' => 'One'];
$this->assertAllowedValuesInput($string, $array, 'Explicit keys are accepted and trimmed.');
}
/**
* Helper function to create list field of a given type.
*
* @param string $type
* 'list_integer', 'list_float' or 'list_string'
*/
protected function createOptionsField($type) {
// Create a field.
FieldStorageConfig::create([
'field_name' => $this->fieldName,
'entity_type' => 'node',
'type' => $type,
])->save();
FieldConfig::create([
'field_name' => $this->fieldName,
'entity_type' => 'node',
'bundle' => $this->type,
])->save();
entity_get_form_display('node', $this->type, 'default')->setComponent($this->fieldName)->save();
$this->adminPath = 'admin/structure/types/manage/' . $this->type . '/fields/node.' . $this->type . '.' . $this->fieldName . '/storage';
}
/**
* Tests a string input for the 'allowed values' form element.
*
* @param $input_string
* The input string, in the pipe-linefeed format expected by the form
* element.
* @param $result
* Either an expected resulting array in
* $field->getSetting('allowed_values'), or an expected error message.
* @param $message
* Message to display.
*/
public function assertAllowedValuesInput($input_string, $result, $message) {
$edit = ['settings[allowed_values]' => $input_string];
$this->drupalPostForm($this->adminPath, $edit, t('Save field settings'));
$this->assertNoRaw('&amp;lt;', 'The page does not have double escaped HTML tags.');
if (is_string($result)) {
$this->assertText($result, $message);
}
else {
$field_storage = FieldStorageConfig::loadByName('node', $this->fieldName);
$this->assertIdentical($field_storage->getSetting('allowed_values'), $result, $message);
}
}
/**
* Tests normal and key formatter display on node display.
*/
public function testNodeDisplay() {
$this->fieldName = strtolower($this->randomMachineName());
$this->createOptionsField('list_integer');
$node = $this->drupalCreateNode(['type' => $this->type]);
$on = $this->randomMachineName();
$off = $this->randomMachineName();
$edit = [
'settings[allowed_values]' =>
"1|$on
0|$off",
];
$this->drupalPostForm($this->adminPath, $edit, t('Save field settings'));
$this->assertText(format_string('Updated field @field_name field settings.', ['@field_name' => $this->fieldName]), "The 'On' and 'Off' form fields work for boolean fields.");
// Select a default value.
$edit = [
$this->fieldName => '1',
];
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save and keep published'));
// Check the node page and see if the values are correct.
$file_formatters = ['list_default', 'list_key'];
foreach ($file_formatters as $formatter) {
$edit = [
"fields[$this->fieldName][type]" => $formatter,
"fields[$this->fieldName][region]" => 'content',
];
$this->drupalPostForm('admin/structure/types/manage/' . $this->typeName . '/display', $edit, t('Save'));
$this->drupalGet('node/' . $node->id());
if ($formatter == 'list_default') {
$output = $on;
}
else {
$output = '1';
}
$elements = $this->xpath('//div[text()="' . $output . '"]');
$this->assertEqual(count($elements), 1, 'Correct options found.');
}
}
}

View file

@ -0,0 +1,72 @@
<?php
namespace Drupal\Tests\options\Functional;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\field\Tests\FieldTestBase;
/**
* Tests option fields can be updated and created through config synchronization.
*
* @group options
*/
class OptionsFloatFieldImportTest extends FieldTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['node', 'options', 'field_ui', 'config', 'options_config_install_test'];
protected function setUp() {
parent::setUp();
// Create test user.
$admin_user = $this->drupalCreateUser(['synchronize configuration', 'access content', 'access administration pages', 'administer site configuration', 'administer content types', 'administer nodes', 'bypass node access', 'administer node fields', 'administer node display']);
$this->drupalLogin($admin_user);
}
/**
* Tests that importing list_float fields works.
*/
public function testImport() {
$field_name = 'field_options_float';
$type = 'options_install_test';
// Test the results on installing options_config_install_test. All the
// necessary configuration for this test is created by installing that
// module.
$field_storage = FieldStorageConfig::loadByName('node', $field_name);
$this->assertIdentical($field_storage->getSetting('allowed_values'), $array = ['0' => 'Zero', '0.5' => 'Point five']);
$admin_path = 'admin/structure/types/manage/' . $type . '/fields/node.' . $type . '.' . $field_name . '/storage';
// Export active config to sync.
$this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.sync'));
// Set the active to not use dots in the allowed values key names.
$edit = ['settings[allowed_values]' => "0|Zero\n1|One"];
$this->drupalPostForm($admin_path, $edit, t('Save field settings'));
$field_storage = FieldStorageConfig::loadByName('node', $field_name);
$this->assertIdentical($field_storage->getSetting('allowed_values'), $array = ['0' => 'Zero', '1' => 'One']);
// Import configuration with dots in the allowed values key names. This
// tests \Drupal\Core\Config\Entity\ConfigEntityStorage::importUpdate().
$this->drupalGet('admin/config/development/configuration');
$this->drupalPostForm(NULL, [], t('Import all'));
$field_storage = FieldStorageConfig::loadByName('node', $field_name);
$this->assertIdentical($field_storage->getSetting('allowed_values'), $array = ['0' => 'Zero', '0.5' => 'Point five']);
// Delete field to test creation. This tests
// \Drupal\Core\Config\Entity\ConfigEntityStorage::importCreate().
FieldConfig::loadByName('node', $type, $field_name)->delete();
$this->drupalGet('admin/config/development/configuration');
$this->drupalPostForm(NULL, [], t('Import all'));
$field_storage = FieldStorageConfig::loadByName('node', $field_name);
$this->assertIdentical($field_storage->getSetting('allowed_values'), $array = ['0' => 'Zero', '0.5' => 'Point five']);
}
}

View file

@ -0,0 +1,34 @@
<?php
namespace Drupal\Tests\options\Functional;
/**
* Tests an options select with a dynamic allowed values function.
*
* @group options
*/
class OptionsSelectDynamicValuesTest extends OptionsDynamicValuesTestBase {
/**
* Tests the 'options_select' widget (single select).
*/
public function testSelectListDynamic() {
// Create an entity.
$this->entity->save();
// Create a web user.
$web_user = $this->drupalCreateUser(['view test entity', 'administer entity_test content']);
$this->drupalLogin($web_user);
// Display form.
$this->drupalGet('entity_test_rev/manage/' . $this->entity->id() . '/edit');
$options = $this->xpath('//select[@id="edit-test-options"]/option');
$this->assertEqual(count($options), count($this->test) + 1);
foreach ($options as $option) {
$value = (string) $option['value'];
if ($value != '_none') {
$this->assertTrue(array_search($value, $this->test));
}
}
}
}

View file

@ -0,0 +1,494 @@
<?php
namespace Drupal\Tests\options\Functional;
use Drupal\entity_test\Entity\EntityTest;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Tests\FieldTestBase;
use Drupal\field\Entity\FieldStorageConfig;
/**
* Tests the Options widgets.
*
* @group options
*/
class OptionsWidgetsTest extends FieldTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['node', 'options', 'entity_test', 'options_test', 'taxonomy', 'field_ui'];
/**
* A field storage with cardinality 1 to use in this test class.
*
* @var \Drupal\field\Entity\FieldStorageConfig
*/
protected $card1;
/**
* A field storage with cardinality 2 to use in this test class.
*
* @var \Drupal\field\Entity\FieldStorageConfig
*/
protected $card2;
protected function setUp() {
parent::setUp();
// Field storage with cardinality 1.
$this->card1 = FieldStorageConfig::create([
'field_name' => 'card_1',
'entity_type' => 'entity_test',
'type' => 'list_integer',
'cardinality' => 1,
'settings' => [
'allowed_values' => [
// Make sure that 0 works as an option.
0 => 'Zero',
1 => 'One',
// Make sure that option text is properly sanitized.
2 => 'Some <script>dangerous</script> & unescaped <strong>markup</strong>',
// Make sure that HTML entities in option text are not double-encoded.
3 => 'Some HTML encoded markup with &lt; &amp; &gt;',
],
],
]);
$this->card1->save();
// Field storage with cardinality 2.
$this->card2 = FieldStorageConfig::create([
'field_name' => 'card_2',
'entity_type' => 'entity_test',
'type' => 'list_integer',
'cardinality' => 2,
'settings' => [
'allowed_values' => [
// Make sure that 0 works as an option.
0 => 'Zero',
1 => 'One',
// Make sure that option text is properly sanitized.
2 => 'Some <script>dangerous</script> & unescaped <strong>markup</strong>',
],
],
]);
$this->card2->save();
// Create a web user.
$this->drupalLogin($this->drupalCreateUser(['view test entity', 'administer entity_test content']));
}
/**
* Tests the 'options_buttons' widget (single select).
*/
public function testRadioButtons() {
// Create an instance of the 'single value' field.
$field = FieldConfig::create([
'field_storage' => $this->card1,
'bundle' => 'entity_test',
]);
$field->save();
entity_get_form_display('entity_test', 'entity_test', 'default')
->setComponent($this->card1->getName(), [
'type' => 'options_buttons',
])
->save();
// Create an entity.
$entity = EntityTest::create([
'user_id' => 1,
'name' => $this->randomMachineName(),
]);
$entity->save();
$entity_init = clone $entity;
// With no field data, no buttons are checked.
$this->drupalGet('entity_test/manage/' . $entity->id() . '/edit');
$this->assertNoFieldChecked('edit-card-1-0');
$this->assertNoFieldChecked('edit-card-1-1');
$this->assertNoFieldChecked('edit-card-1-2');
$this->assertRaw('Some dangerous &amp; unescaped <strong>markup</strong>', 'Option text was properly filtered.');
$this->assertRaw('Some HTML encoded markup with &lt; &amp; &gt;');
// Select first option.
$edit = ['card_1' => 0];
$this->drupalPostForm(NULL, $edit, t('Save'));
$this->assertFieldValues($entity_init, 'card_1', [0]);
// Check that the selected button is checked.
$this->drupalGet('entity_test/manage/' . $entity->id() . '/edit');
$this->assertFieldChecked('edit-card-1-0');
$this->assertNoFieldChecked('edit-card-1-1');
$this->assertNoFieldChecked('edit-card-1-2');
// Unselect option.
$edit = ['card_1' => '_none'];
$this->drupalPostForm(NULL, $edit, t('Save'));
$this->assertFieldValues($entity_init, 'card_1', []);
// Check that required radios with one option is auto-selected.
$this->card1->setSetting('allowed_values', [99 => 'Only allowed value']);
$this->card1->save();
$field->setRequired(TRUE);
$field->save();
$this->drupalGet('entity_test/manage/' . $entity->id() . '/edit');
$this->assertFieldChecked('edit-card-1-99');
}
/**
* Tests the 'options_buttons' widget (multiple select).
*/
public function testCheckBoxes() {
// Create an instance of the 'multiple values' field.
$field = FieldConfig::create([
'field_storage' => $this->card2,
'bundle' => 'entity_test',
]);
$field->save();
entity_get_form_display('entity_test', 'entity_test', 'default')
->setComponent($this->card2->getName(), [
'type' => 'options_buttons',
])
->save();
// Create an entity.
$entity = EntityTest::create([
'user_id' => 1,
'name' => $this->randomMachineName(),
]);
$entity->save();
$entity_init = clone $entity;
// Display form: with no field data, nothing is checked.
$this->drupalGet('entity_test/manage/' . $entity->id() . '/edit');
$this->assertNoFieldChecked('edit-card-2-0');
$this->assertNoFieldChecked('edit-card-2-1');
$this->assertNoFieldChecked('edit-card-2-2');
$this->assertRaw('Some dangerous &amp; unescaped <strong>markup</strong>', 'Option text was properly filtered.');
// Submit form: select first and third options.
$edit = [
'card_2[0]' => TRUE,
'card_2[1]' => FALSE,
'card_2[2]' => TRUE,
];
$this->drupalPostForm(NULL, $edit, t('Save'));
$this->assertFieldValues($entity_init, 'card_2', [0, 2]);
// Display form: check that the right options are selected.
$this->drupalGet('entity_test/manage/' . $entity->id() . '/edit');
$this->assertFieldChecked('edit-card-2-0');
$this->assertNoFieldChecked('edit-card-2-1');
$this->assertFieldChecked('edit-card-2-2');
// Submit form: select only first option.
$edit = [
'card_2[0]' => TRUE,
'card_2[1]' => FALSE,
'card_2[2]' => FALSE,
];
$this->drupalPostForm(NULL, $edit, t('Save'));
$this->assertFieldValues($entity_init, 'card_2', [0]);
// Display form: check that the right options are selected.
$this->drupalGet('entity_test/manage/' . $entity->id() . '/edit');
$this->assertFieldChecked('edit-card-2-0');
$this->assertNoFieldChecked('edit-card-2-1');
$this->assertNoFieldChecked('edit-card-2-2');
// Submit form: select the three options while the field accepts only 2.
$edit = [
'card_2[0]' => TRUE,
'card_2[1]' => TRUE,
'card_2[2]' => TRUE,
];
$this->drupalPostForm(NULL, $edit, t('Save'));
$this->assertText('this field cannot hold more than 2 values', 'Validation error was displayed.');
// Submit form: uncheck all options.
$edit = [
'card_2[0]' => FALSE,
'card_2[1]' => FALSE,
'card_2[2]' => FALSE,
];
$this->drupalPostForm(NULL, $edit, t('Save'));
// Check that the value was saved.
$this->assertFieldValues($entity_init, 'card_2', []);
// Required checkbox with one option is auto-selected.
$this->card2->setSetting('allowed_values', [99 => 'Only allowed value']);
$this->card2->save();
$field->setRequired(TRUE);
$field->save();
$this->drupalGet('entity_test/manage/' . $entity->id() . '/edit');
$this->assertFieldChecked('edit-card-2-99');
}
/**
* Tests the 'options_select' widget (single select).
*/
public function testSelectListSingle() {
// Create an instance of the 'single value' field.
$field = FieldConfig::create([
'field_storage' => $this->card1,
'bundle' => 'entity_test',
'required' => TRUE,
]);
$field->save();
entity_get_form_display('entity_test', 'entity_test', 'default')
->setComponent($this->card1->getName(), [
'type' => 'options_select',
])
->save();
// Create an entity.
$entity = EntityTest::create([
'user_id' => 1,
'name' => $this->randomMachineName(),
]);
$entity->save();
$entity_init = clone $entity;
// Display form.
$this->drupalGet('entity_test/manage/' . $entity->id() . '/edit');
// A required field without any value has a "none" option.
$this->assertTrue($this->xpath('//select[@id=:id]//option[@value="_none" and text()=:label]', [':id' => 'edit-card-1', ':label' => t('- Select a value -')]), 'A required select list has a "Select a value" choice.');
// With no field data, nothing is selected.
$this->assertNoOptionSelected('edit-card-1', '_none');
$this->assertNoOptionSelected('edit-card-1', 0);
$this->assertNoOptionSelected('edit-card-1', 1);
$this->assertNoOptionSelected('edit-card-1', 2);
$this->assertRaw('Some dangerous &amp; unescaped markup', 'Option text was properly filtered.');
// Submit form: select invalid 'none' option.
$edit = ['card_1' => '_none'];
$this->drupalPostForm(NULL, $edit, t('Save'));
$this->assertRaw(t('@title field is required.', ['@title' => $field->getName()]), 'Cannot save a required field when selecting "none" from the select list.');
// Submit form: select first option.
$edit = ['card_1' => 0];
$this->drupalPostForm(NULL, $edit, t('Save'));
$this->assertFieldValues($entity_init, 'card_1', [0]);
// Display form: check that the right options are selected.
$this->drupalGet('entity_test/manage/' . $entity->id() . '/edit');
// A required field with a value has no 'none' option.
$this->assertFalse($this->xpath('//select[@id=:id]//option[@value="_none"]', [':id' => 'edit-card-1']), 'A required select list with an actual value has no "none" choice.');
$this->assertOptionSelected('edit-card-1', 0);
$this->assertNoOptionSelected('edit-card-1', 1);
$this->assertNoOptionSelected('edit-card-1', 2);
// Make the field non required.
$field->setRequired(FALSE);
$field->save();
// Display form.
$this->drupalGet('entity_test/manage/' . $entity->id() . '/edit');
// A non-required field has a 'none' option.
$this->assertTrue($this->xpath('//select[@id=:id]//option[@value="_none" and text()=:label]', [':id' => 'edit-card-1', ':label' => t('- None -')]), 'A non-required select list has a "None" choice.');
// Submit form: Unselect the option.
$edit = ['card_1' => '_none'];
$this->drupalPostForm('entity_test/manage/' . $entity->id() . '/edit', $edit, t('Save'));
$this->assertFieldValues($entity_init, 'card_1', []);
// Test optgroups.
$this->card1->setSetting('allowed_values', []);
$this->card1->setSetting('allowed_values_function', 'options_test_allowed_values_callback');
$this->card1->save();
// Display form: with no field data, nothing is selected
$this->drupalGet('entity_test/manage/' . $entity->id() . '/edit');
$this->assertNoOptionSelected('edit-card-1', 0);
$this->assertNoOptionSelected('edit-card-1', 1);
$this->assertNoOptionSelected('edit-card-1', 2);
$this->assertRaw('Some dangerous &amp; unescaped markup', 'Option text was properly filtered.');
$this->assertRaw('More &lt;script&gt;dangerous&lt;/script&gt; markup', 'Option group text was properly filtered.');
$this->assertRaw('Group 1', 'Option groups are displayed.');
// Submit form: select first option.
$edit = ['card_1' => 0];
$this->drupalPostForm(NULL, $edit, t('Save'));
$this->assertFieldValues($entity_init, 'card_1', [0]);
// Display form: check that the right options are selected.
$this->drupalGet('entity_test/manage/' . $entity->id() . '/edit');
$this->assertOptionSelected('edit-card-1', 0);
$this->assertNoOptionSelected('edit-card-1', 1);
$this->assertNoOptionSelected('edit-card-1', 2);
// Submit form: Unselect the option.
$edit = ['card_1' => '_none'];
$this->drupalPostForm('entity_test/manage/' . $entity->id() . '/edit', $edit, t('Save'));
$this->assertFieldValues($entity_init, 'card_1', []);
}
/**
* Tests the 'options_select' widget (multiple select).
*/
public function testSelectListMultiple() {
// Create an instance of the 'multiple values' field.
$field = FieldConfig::create([
'field_storage' => $this->card2,
'bundle' => 'entity_test',
]);
$field->save();
entity_get_form_display('entity_test', 'entity_test', 'default')
->setComponent($this->card2->getName(), [
'type' => 'options_select',
])
->save();
// Create an entity.
$entity = EntityTest::create([
'user_id' => 1,
'name' => $this->randomMachineName(),
]);
$entity->save();
$entity_init = clone $entity;
// Display form: with no field data, nothing is selected.
$this->drupalGet('entity_test/manage/' . $entity->id() . '/edit');
$this->assertOptionSelected("edit-card-2", '_none');
$this->assertNoOptionSelected('edit-card-2', 0);
$this->assertNoOptionSelected('edit-card-2', 1);
$this->assertNoOptionSelected('edit-card-2', 2);
$this->assertRaw('Some dangerous &amp; unescaped markup', 'Option text was properly filtered.');
// Submit form: select first and third options.
$edit = ['card_2[]' => [0 => 0, 2 => 2]];
$this->drupalPostForm(NULL, $edit, t('Save'));
$this->assertFieldValues($entity_init, 'card_2', [0, 2]);
// Display form: check that the right options are selected.
$this->drupalGet('entity_test/manage/' . $entity->id() . '/edit');
$this->assertOptionSelected('edit-card-2', 0);
$this->assertNoOptionSelected('edit-card-2', 1);
$this->assertOptionSelected('edit-card-2', 2);
// Submit form: select only first option.
$edit = ['card_2[]' => [0 => 0]];
$this->drupalPostForm(NULL, $edit, t('Save'));
$this->assertFieldValues($entity_init, 'card_2', [0]);
// Display form: check that the right options are selected.
$this->drupalGet('entity_test/manage/' . $entity->id() . '/edit');
$this->assertOptionSelected('edit-card-2', 0);
$this->assertNoOptionSelected('edit-card-2', 1);
$this->assertNoOptionSelected('edit-card-2', 2);
// Submit form: select the three options while the field accepts only 2.
$edit = ['card_2[]' => [0 => 0, 1 => 1, 2 => 2]];
$this->drupalPostForm(NULL, $edit, t('Save'));
$this->assertText('this field cannot hold more than 2 values', 'Validation error was displayed.');
// Submit form: uncheck all options.
$edit = ['card_2[]' => []];
$this->drupalPostForm(NULL, $edit, t('Save'));
$this->assertFieldValues($entity_init, 'card_2', []);
// Test the 'None' option.
// Check that the 'none' option has no effect if actual options are selected
// as well.
$edit = ['card_2[]' => ['_none' => '_none', 0 => 0]];
$this->drupalPostForm('entity_test/manage/' . $entity->id() . '/edit', $edit, t('Save'));
$this->assertFieldValues($entity_init, 'card_2', [0]);
// Check that selecting the 'none' option empties the field.
$edit = ['card_2[]' => ['_none' => '_none']];
$this->drupalPostForm('entity_test/manage/' . $entity->id() . '/edit', $edit, t('Save'));
$this->assertFieldValues($entity_init, 'card_2', []);
// A required select list does not have an empty key.
$field->setRequired(TRUE);
$field->save();
$this->drupalGet('entity_test/manage/' . $entity->id() . '/edit');
$this->assertFalse($this->xpath('//select[@id=:id]//option[@value=""]', [':id' => 'edit-card-2']), 'A required select list does not have an empty key.');
// We do not have to test that a required select list with one option is
// auto-selected because the browser does it for us.
// Test optgroups.
// Use a callback function defining optgroups.
$this->card2->setSetting('allowed_values', []);
$this->card2->setSetting('allowed_values_function', 'options_test_allowed_values_callback');
$this->card2->save();
$field->setRequired(FALSE);
$field->save();
// Display form: with no field data, nothing is selected.
$this->drupalGet('entity_test/manage/' . $entity->id() . '/edit');
$this->assertNoOptionSelected('edit-card-2', 0);
$this->assertNoOptionSelected('edit-card-2', 1);
$this->assertNoOptionSelected('edit-card-2', 2);
$this->assertRaw('Some dangerous &amp; unescaped markup', 'Option text was properly filtered.');
$this->assertRaw('More &lt;script&gt;dangerous&lt;/script&gt; markup', 'Option group text was properly filtered.');
$this->assertRaw('Group 1', 'Option groups are displayed.');
// Submit form: select first option.
$edit = ['card_2[]' => [0 => 0]];
$this->drupalPostForm(NULL, $edit, t('Save'));
$this->assertFieldValues($entity_init, 'card_2', [0]);
// Display form: check that the right options are selected.
$this->drupalGet('entity_test/manage/' . $entity->id() . '/edit');
$this->assertOptionSelected('edit-card-2', 0);
$this->assertNoOptionSelected('edit-card-2', 1);
$this->assertNoOptionSelected('edit-card-2', 2);
// Submit form: Unselect the option.
$edit = ['card_2[]' => ['_none' => '_none']];
$this->drupalPostForm('entity_test/manage/' . $entity->id() . '/edit', $edit, t('Save'));
$this->assertFieldValues($entity_init, 'card_2', []);
}
/**
* Tests the 'options_select' and 'options_button' widget for empty value.
*/
public function testEmptyValue() {
// Create an instance of the 'single value' field.
$field = FieldConfig::create([
'field_storage' => $this->card1,
'bundle' => 'entity_test',
]);
$field->save();
// Change it to the check boxes/radio buttons widget.
entity_get_form_display('entity_test', 'entity_test', 'default')
->setComponent($this->card1->getName(), [
'type' => 'options_buttons',
])
->save();
// Create an entity.
$entity = EntityTest::create([
'user_id' => 1,
'name' => $this->randomMachineName(),
]);
$entity->save();
// Display form: check that _none options are present and has label.
$this->drupalGet('entity_test/manage/' . $entity->id() . '/edit');
$this->assertTrue($this->xpath('//div[@id=:id]//input[@value=:value]', [':id' => 'edit-card-1', ':value' => '_none']), 'A test radio button has a "None" choice.');
$this->assertTrue($this->xpath('//div[@id=:id]//label[@for=:for and text()=:label]', [':id' => 'edit-card-1', ':for' => 'edit-card-1-none', ':label' => 'N/A']), 'A test radio button has a "N/A" choice.');
// Change it to the select widget.
entity_get_form_display('entity_test', 'entity_test', 'default')
->setComponent($this->card1->getName(), [
'type' => 'options_select',
])
->save();
// Display form: check that _none options are present and has label.
$this->drupalGet('entity_test/manage/' . $entity->id() . '/edit');
// A required field without any value has a "none" option.
$this->assertTrue($this->xpath('//select[@id=:id]//option[@value="_none" and text()=:label]', [':id' => 'edit-card-1', ':label' => t('- None -')]), 'A test select has a "None" choice.');
}
}

View file

@ -19,12 +19,12 @@ class OptionsFieldTest extends OptionsFieldUnitTestBase {
*
* @var array
*/
public static $modules = array('options');
public static $modules = ['options'];
/**
* Test that allowed values can be updated.
*/
function testUpdateAllowedValues() {
public function testUpdateAllowedValues() {
// All three options appear.
$entity = EntityTest::create();
$form = \Drupal::service('entity.form_builder')->getForm($entity);
@ -81,9 +81,9 @@ class OptionsFieldTest extends OptionsFieldUnitTestBase {
'required' => TRUE,
])->save();
entity_get_form_display('entity_test', 'entity_test', 'default')
->setComponent($this->fieldName, array(
->setComponent($this->fieldName, [
'type' => 'options_buttons',
))
])
->save();
$entity = EntityTest::create();
$form = \Drupal::service('entity.form_builder')->getForm($entity);

View file

@ -16,7 +16,7 @@ abstract class OptionsFieldUnitTestBase extends FieldKernelTestBase {
*
* @var array
*/
public static $modules = array('options');
public static $modules = ['options'];
/**
* The field name used in the test.
@ -53,15 +53,15 @@ abstract class OptionsFieldUnitTestBase extends FieldKernelTestBase {
parent::setUp();
$this->container->get('router.builder')->rebuild();
$this->fieldStorageDefinition = array(
$this->fieldStorageDefinition = [
'field_name' => $this->fieldName,
'entity_type' => 'entity_test',
'type' => 'list_integer',
'cardinality' => 1,
'settings' => array(
'allowed_values' => array(1 => 'One', 2 => 'Two', 3 => 'Three'),
),
);
'settings' => [
'allowed_values' => [1 => 'One', 2 => 'Two', 3 => 'Three'],
],
];
$this->fieldStorage = FieldStorageConfig::create($this->fieldStorageDefinition);
$this->fieldStorage->save();
@ -72,9 +72,9 @@ abstract class OptionsFieldUnitTestBase extends FieldKernelTestBase {
$this->field->save();
entity_get_form_display('entity_test', 'entity_test', 'default')
->setComponent($this->fieldName, array(
->setComponent($this->fieldName, [
'type' => 'options_buttons',
))
])
->save();
}

View file

@ -33,7 +33,7 @@ class OptionsFormattersTest extends OptionsFieldUnitTestBase {
$this->assertEqual($build['#formatter'], 'list_default', 'Ensure to fall back to the default formatter.');
$this->assertEqual($build[0]['#markup'], 'One');
$build = $items->view(array('type' => 'list_key'));
$build = $items->view(['type' => 'list_key']);
$this->assertEqual($build['#formatter'], 'list_key', 'The chosen formatter is used.');
$this->assertEqual((string) $build[0]['#markup'], 1);
}

View file

@ -19,7 +19,7 @@ class FileViewsDataTest extends ViewsKernelTestBase {
*
* @var array
*/
public static $modules = array('file', 'views', 'entity_test', 'user', 'field');
public static $modules = ['file', 'views', 'entity_test', 'user', 'field'];
/**
* Tests views data generated for file field relationship.
@ -29,16 +29,16 @@ class FileViewsDataTest extends ViewsKernelTestBase {
*/
public function testRelationshipViewsData() {
// Create file field to entity_test.
FieldStorageConfig::create(array(
FieldStorageConfig::create([
'entity_type' => 'entity_test',
'field_name' => 'field_base_file',
'type' => 'file',
))->save();
FieldConfig::create(array(
])->save();
FieldConfig::create([
'entity_type' => 'entity_test',
'field_name' => 'field_base_file',
'bundle' => 'entity_test',
))->save();
])->save();
// Check the generated views data.
$views_data = Views::viewsData()->get('entity_test__field_base_file');
$relationship = $views_data['field_base_file_target_id']['relationship'];
@ -59,16 +59,16 @@ class FileViewsDataTest extends ViewsKernelTestBase {
$this->assertEqual($relationship['join_extra'][0], ['field' => 'deleted', 'value' => 0, 'numeric' => TRUE]);
// Create file field to entity_test_mul.
FieldStorageConfig::create(array(
FieldStorageConfig::create([
'entity_type' => 'entity_test_mul',
'field_name' => 'field_data_file',
'type' => 'file',
))->save();
FieldConfig::create(array(
])->save();
FieldConfig::create([
'entity_type' => 'entity_test_mul',
'field_name' => 'field_data_file',
'bundle' => 'entity_test_mul',
))->save();
])->save();
// Check the generated views data.
$views_data = Views::viewsData()->get('entity_test_mul__field_data_file');
$relationship = $views_data['field_data_file_target_id']['relationship'];

View file

@ -35,4 +35,78 @@ class OptionsListFilterTest extends OptionsTestBase {
$this->assertIdenticalResultset($view, $resultset, $column_map);
}
/**
* Tests options list field filter when grouped.
*/
public function testViewsTestOptionsListGroupedFilter() {
$view = Views::getView('test_options_list_filter');
$filters = [
'field_test_list_string_value' => [
'id' => 'field_test_list_string_value',
'table' => 'field_data_field_test_list_string',
'field' => 'field_test_list_string_value',
'relationship' => 'none',
'group_type' => 'group',
'admin_label' => '',
'operator' => 'or',
'value' => [
'man' => 'man',
'woman' => 'woman',
],
'group' => '1',
'exposed' => TRUE,
'expose' => [
'operator_id' => 'field_test_list_string_value_op',
'label' => 'list-text',
'description' => '',
'identifier' => 'field_test_list_string_value',
],
'is_grouped' => TRUE,
'group_info' => [
'label' => 'list-text (field_list_text)',
'description' => '',
'identifier' => 'field_test_list_string_value',
'optional' => TRUE,
'widget' => 'radios',
'multiple' => TRUE,
'remember' => FALSE,
'default_group' => '1',
'group_items' => [
1 => [
'title' => 'First',
'operator' => 'or',
'value' => [
$this->fieldValues[0] => $this->fieldValues[0],
]
],
2 => [
'title' => 'Second',
'operator' => 'or',
'value' => [
$this->fieldValues[1] => $this->fieldValues[1],
]
],
],
],
'reduce_duplicates' => '',
'plugin_id' => 'list_field',
]
];
$view->setDisplay();
$view->displayHandlers->get('default')->overrideOption('filters', $filters);
$view->storage->save();
$this->executeView($view);
$resultset = [
['nid' => $this->nodes[0]->nid->value],
['nid' => $this->nodes[1]->nid->value],
];
$column_map = ['nid' => 'nid'];
$this->assertIdenticalResultset($view, $resultset, $column_map);
}
}