diff --git a/core/includes/form.inc b/core/includes/form.inc index 9c72685..a2f4ce6 100644 --- a/core/includes/form.inc +++ b/core/includes/form.inc @@ -17,6 +17,7 @@ use Drupal\Core\Template\Attribute; use Drupal\Core\Url; use Symfony\Component\HttpFoundation\RedirectResponse; +use Drupal\Core\Field\Plugin\Field\FieldWidget\OptionsWidgetBase; /** * Retrieves, populates, and processes a form. @@ -118,7 +119,7 @@ function form_select_options($element, $choices = NULL) { } else { $key = (string) $key; - $empty_choice = $empty_value && $key == '_none'; + $empty_choice = $empty_value && $key == OptionsWidgetBase::OPTIONS_EMPTY_OPTION; if ($value_valid && ((!$value_is_array && (string) $element['#value'] === $key || ($value_is_array && in_array($key, $element['#value']))) || $empty_choice)) { $selected = ' selected="selected"'; } diff --git a/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/SelectionBase.php b/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/SelectionBase.php index f33fe2a..ae2933d 100644 --- a/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/SelectionBase.php +++ b/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/SelectionBase.php @@ -18,6 +18,7 @@ use Drupal\Core\Plugin\PluginBase; use Drupal\Core\Session\AccountInterface; use Symfony\Component\DependencyInjection\ContainerInterface; +use Drupal\Core\Field\Plugin\Field\FieldWidget\OptionsWidgetBase; /** * Default plugin implementation of the Entity Reference Selection plugin. @@ -113,7 +114,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta $selection_handler_settings += array( 'target_bundles' => array(), 'sort' => array( - 'field' => '_none', + 'field' => OptionsWidgetBase::OPTIONS_EMPTY_OPTION, ), 'auto_create' => FALSE, ); @@ -169,7 +170,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta '#type' => 'select', '#title' => $this->t('Sort by'), '#options' => array( - '_none' => $this->t('- None -'), + OptionsWidgetBase::OPTIONS_EMPTY_OPTION => $this->t('- None -'), ) + $fields, '#ajax' => TRUE, '#limit_validation_errors' => array(), @@ -182,7 +183,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta '#process' => array('_entity_reference_form_process_merge_parent'), ); - if ($selection_handler_settings['sort']['field'] != '_none') { + if ($selection_handler_settings['sort']['field'] != OptionsWidgetBase::OPTIONS_EMPTY_OPTION) { // Merge-in default values. $selection_handler_settings['sort'] += array( 'direction' => 'ASC', @@ -345,7 +346,7 @@ protected function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') // Add the sort option. if (!empty($handler_settings['sort'])) { $sort_settings = $handler_settings['sort']; - if ($sort_settings['field'] != '_none') { + if ($sort_settings['field'] != OptionsWidgetBase::OPTIONS_EMPTY_OPTION) { $query->sort($sort_settings['field'], $sort_settings['direction']); } } diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/OptionsWidgetBase.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/OptionsWidgetBase.php index b155c3b..c6b54eb 100644 --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/OptionsWidgetBase.php +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/OptionsWidgetBase.php @@ -36,6 +36,12 @@ */ const OPTIONS_EMPTY_SELECT = 'option_select'; + + /** + * Identifies a 'None' option key. + */ + const OPTIONS_EMPTY_OPTION = '_none'; + /** * Abstract over the actual field columns, to allow different field types to * reuse those widgets. @@ -81,7 +87,7 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen * The form state. */ public static function validateElement(array $element, FormStateInterface $form_state) { - if ($element['#required'] && $element['#value'] == '_none') { + if ($element['#required'] && $element['#value'] == static::OPTIONS_EMPTY_OPTION) { $form_state->setError($element, t('!name field is required.', array('!name' => $element['#title']))); } @@ -99,7 +105,7 @@ public static function validateElement(array $element, FormStateInterface $form_ // Filter out the 'none' option. Use a strict comparison, because // 0 == 'any string'. - $index = array_search('_none', $values, TRUE); + $index = array_search(static::OPTIONS_EMPTY_OPTION, $values, TRUE); if ($index !== FALSE) { unset($values[$index]); } @@ -141,7 +147,7 @@ protected function getOptions(FieldableEntityInterface $entity) { break; } - $options = array('_none' => $label) + $options; + $options = array(static::OPTIONS_EMPTY_OPTION => $label) + $options; } $module_handler = \Drupal::moduleHandler(); diff --git a/core/modules/entity_reference/src/Tests/EntityReferenceAdminTest.php b/core/modules/entity_reference/src/Tests/EntityReferenceAdminTest.php index e6718c0..47fac1f 100644 --- a/core/modules/entity_reference/src/Tests/EntityReferenceAdminTest.php +++ b/core/modules/entity_reference/src/Tests/EntityReferenceAdminTest.php @@ -10,6 +10,7 @@ use Drupal\field_ui\Tests\FieldUiTestTrait; use Drupal\simpletest\WebTestBase; use Drupal\taxonomy\Entity\Vocabulary; +use Drupal\Core\Field\Plugin\Field\FieldWidget\OptionsWidgetBase; /** * Tests for the administrative UI. @@ -97,7 +98,7 @@ public function testFieldAdminHandler() { // Test the sort settings. // Option 0: no sort. - $this->assertFieldByName('field[settings][handler_settings][sort][field]', '_none'); + $this->assertFieldByName('field[settings][handler_settings][sort][field]', OptionsWidgetBase::OPTIONS_EMPTY_OPTION); $this->assertNoFieldByName('field[settings][handler_settings][sort][direction]'); // Option 1: sort by field. $this->drupalPostAjaxForm(NULL, array('field[settings][handler_settings][sort][field]' => 'nid'), 'field[settings][handler_settings][sort][field]'); @@ -111,7 +112,7 @@ public function testFieldAdminHandler() { $this->assertFieldByXPath("//select[@name='field[settings][handler_settings][sort][field]']/option[@value='body.value']"); // Set back to no sort. - $this->drupalPostAjaxForm(NULL, array('field[settings][handler_settings][sort][field]' => '_none'), 'field[settings][handler_settings][sort][field]'); + $this->drupalPostAjaxForm(NULL, array('field[settings][handler_settings][sort][field]' => OptionsWidgetBase::OPTIONS_EMPTY_OPTION), 'field[settings][handler_settings][sort][field]'); $this->assertNoFieldByName('field[settings][handler_settings][sort][direction]'); // Third step: confirm. @@ -147,7 +148,7 @@ public function testFieldAdminHandler() { ); $this->drupalPostForm($bundle_path . '/fields/' . $field_name . '/storage', $edit, t('Save field settings')); $this->drupalGet($bundle_path . '/fields/' . $field_name); - $this->assertFieldByName('field[settings][handler_settings][filter][type]', '_none'); + $this->assertFieldByName('field[settings][handler_settings][filter][type]', OptionsWidgetBase::OPTIONS_EMPTY_OPTION); // Try to select the views handler. $edit = array( diff --git a/core/modules/entity_reference/src/Tests/EntityReferenceFieldDefaultValueTest.php b/core/modules/entity_reference/src/Tests/EntityReferenceFieldDefaultValueTest.php index c2ceed9..b71f078 100644 --- a/core/modules/entity_reference/src/Tests/EntityReferenceFieldDefaultValueTest.php +++ b/core/modules/entity_reference/src/Tests/EntityReferenceFieldDefaultValueTest.php @@ -11,6 +11,7 @@ use Drupal\config\Tests\SchemaCheckTestTrait; use Drupal\field\Entity\FieldStorageConfig; use Drupal\simpletest\WebTestBase; +use Drupal\Core\Field\Plugin\Field\FieldWidget\OptionsWidgetBase; /** * Tests entity reference field default values storage in CMI. @@ -68,7 +69,7 @@ function testEntityReferenceDefaultValue() { 'handler' => 'default', 'handler_settings' => array( 'target_bundles' => array('referenced_content'), - 'sort' => array('field' => '_none'), + 'sort' => array('field' => OptionsWidgetBase::OPTIONS_EMPTY_OPTION), ), ), )); @@ -131,7 +132,7 @@ function testEntityReferenceDefaultConfigValue() { 'settings' => array( 'handler' => 'default', 'handler_settings' => array( - 'sort' => array('field' => '_none'), + 'sort' => array('field' => OptionsWidgetBase::OPTIONS_EMPTY_OPTION), ), ), )); diff --git a/core/modules/options/options.api.php b/core/modules/options/options.api.php index c1dd934..3ba6dc9 100644 --- a/core/modules/options/options.api.php +++ b/core/modules/options/options.api.php @@ -7,6 +7,7 @@ use Drupal\Core\Entity\FieldableEntityInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface; +use Drupal\Core\Field\Plugin\Field\FieldWidget\OptionsWidgetBase; /** * Alters the list of options to be displayed for a field. @@ -32,7 +33,7 @@ function hook_options_list_alter(array &$options, array $context) { // Check if this is the field we want to change. if ($context['field']->id() == 'field_option') { // Change the label of the empty option. - $options[OPTIONS_EMPTY_NONE] = t('== Empty =='); + $options[OptionsWidgetBase::OPTIONS_EMPTY_OPTION] = t('== Empty =='); } } diff --git a/core/modules/options/options.module b/core/modules/options/options.module index 78020a0..d221adb 100644 --- a/core/modules/options/options.module +++ b/core/modules/options/options.module @@ -12,11 +12,6 @@ use Drupal\field\FieldStorageConfigInterface; /** - * Identifies a 'None' option. - */ -const OPTIONS_EMPTY_NONE = '_none'; - -/** * Implements hook_help(). */ function options_help($route_name, RouteMatchInterface $route_match) { diff --git a/core/modules/options/src/Tests/OptionsSelectDynamicValuesTest.php b/core/modules/options/src/Tests/OptionsSelectDynamicValuesTest.php index 1fef8ec..2f422cd 100644 --- a/core/modules/options/src/Tests/OptionsSelectDynamicValuesTest.php +++ b/core/modules/options/src/Tests/OptionsSelectDynamicValuesTest.php @@ -7,6 +7,8 @@ namespace Drupal\options\Tests; +use Drupal\Core\Field\Plugin\Field\FieldWidget\OptionsWidgetBase; + /** * Tests an options select with a dynamic allowed values function. * @@ -30,7 +32,7 @@ function testSelectListDynamic() { $this->assertEqual(count($options), count($this->test) + 1); foreach ($options as $option) { $value = (string) $option['value']; - if ($value != OPTIONS_EMPTY_NONE) { + if ($value != OptionsWidgetBase::OPTIONS_EMPTY_OPTION) { $this->assertTrue(array_search($value, $this->test)); } } diff --git a/core/modules/options/src/Tests/OptionsWidgetsTest.php b/core/modules/options/src/Tests/OptionsWidgetsTest.php index ae7bc2a..a8f8fd1 100644 --- a/core/modules/options/src/Tests/OptionsWidgetsTest.php +++ b/core/modules/options/src/Tests/OptionsWidgetsTest.php @@ -8,6 +8,7 @@ namespace Drupal\options\Tests; use Drupal\field\Tests\FieldTestBase; +use Drupal\Core\Field\Plugin\Field\FieldWidget\OptionsWidgetBase; /** * Tests the Options widgets. @@ -127,7 +128,7 @@ function testRadioButtons() { $this->assertNoFieldChecked('edit-card-1-2'); // Unselect option. - $edit = array('card_1' => OPTIONS_EMPTY_NONE); + $edit = array('card_1' => OptionsWidgetBase::OPTIONS_EMPTY_OPTION); $this->drupalPostForm(NULL, $edit, t('Save')); $this->assertFieldValues($entity_init, 'card_1', array()); @@ -260,14 +261,14 @@ function testSelectListSingle() { $this->assertTrue($this->xpath('//select[@id=:id]//option[@value="_none" and text()=:label]', array(':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', OPTIONS_EMPTY_NONE); + $this->assertNoOptionSelected('edit-card-1', OptionsWidgetBase::OPTIONS_EMPTY_OPTION); $this->assertNoOptionSelected('edit-card-1', 0); $this->assertNoOptionSelected('edit-card-1', 1); $this->assertNoOptionSelected('edit-card-1', 2); $this->assertRaw('Some dangerous & unescaped markup', 'Option text was properly filtered.'); // Submit form: select invalid 'none' option. - $edit = array('card_1' => OPTIONS_EMPTY_NONE); + $edit = array('card_1' => OptionsWidgetBase::OPTIONS_EMPTY_OPTION); $this->drupalPostForm(NULL, $edit, t('Save')); $this->assertRaw(t('!title field is required.', array('!title' => $field->getName())), 'Cannot save a required field when selecting "none" from the select list.'); @@ -293,7 +294,7 @@ function testSelectListSingle() { // A non-required field has a 'none' option. $this->assertTrue($this->xpath('//select[@id=:id]//option[@value="_none" and text()=:label]', array(':id' => 'edit-card-1', ':label' => t('- None -'))), 'A non-required select list has a "None" choice.'); // Submit form: Unselect the option. - $edit = array('card_1' => OPTIONS_EMPTY_NONE); + $edit = array('card_1' => OptionsWidgetBase::OPTIONS_EMPTY_OPTION); $this->drupalPostForm('entity_test/manage/' . $entity->id(), $edit, t('Save')); $this->assertFieldValues($entity_init, 'card_1', array()); @@ -324,7 +325,7 @@ function testSelectListSingle() { $this->assertNoOptionSelected('edit-card-1', 2); // Submit form: Unselect the option. - $edit = array('card_1' => OPTIONS_EMPTY_NONE); + $edit = array('card_1' => OptionsWidgetBase::OPTIONS_EMPTY_OPTION); $this->drupalPostForm('entity_test/manage/' . $entity->id(), $edit, t('Save')); $this->assertFieldValues($entity_init, 'card_1', array()); } @@ -355,7 +356,7 @@ function testSelectListMultiple() { // Display form: with no field data, nothing is selected. $this->drupalGet('entity_test/manage/' . $entity->id()); - $this->assertOptionSelected("edit-card-2", OPTIONS_EMPTY_NONE); + $this->assertOptionSelected("edit-card-2", OptionsWidgetBase::OPTIONS_EMPTY_OPTION); $this->assertNoOptionSelected('edit-card-2', 0); $this->assertNoOptionSelected('edit-card-2', 1); $this->assertNoOptionSelected('edit-card-2', 2); @@ -397,12 +398,12 @@ function testSelectListMultiple() { // Check that the 'none' option has no effect if actual options are selected // as well. - $edit = array('card_2[]' => array(OPTIONS_EMPTY_NONE => OPTIONS_EMPTY_NONE, 0 => 0)); + $edit = array('card_2[]' => array(OptionsWidgetBase::OPTIONS_EMPTY_OPTION => OptionsWidgetBase::OPTIONS_EMPTY_OPTION, 0 => 0)); $this->drupalPostForm('entity_test/manage/' . $entity->id(), $edit, t('Save')); $this->assertFieldValues($entity_init, 'card_2', array(0)); // Check that selecting the 'none' option empties the field. - $edit = array('card_2[]' => array(OPTIONS_EMPTY_NONE => OPTIONS_EMPTY_NONE)); + $edit = array('card_2[]' => array(OptionsWidgetBase::OPTIONS_EMPTY_OPTION => OptionsWidgetBase::OPTIONS_EMPTY_OPTION)); $this->drupalPostForm('entity_test/manage/' . $entity->id(), $edit, t('Save')); $this->assertFieldValues($entity_init, 'card_2', array()); @@ -445,7 +446,7 @@ function testSelectListMultiple() { $this->assertNoOptionSelected('edit-card-2', 2); // Submit form: Unselect the option. - $edit = array('card_2[]' => array(OPTIONS_EMPTY_NONE => OPTIONS_EMPTY_NONE)); + $edit = array('card_2[]' => array(OptionsWidgetBase::OPTIONS_EMPTY_OPTION => OptionsWidgetBase::OPTIONS_EMPTY_OPTION)); $this->drupalPostForm('entity_test/manage/' . $entity->id(), $edit, t('Save')); $this->assertFieldValues($entity_init, 'card_2', array()); } diff --git a/core/modules/system/src/Tests/Entity/EntityCacheTagsTestBase.php b/core/modules/system/src/Tests/Entity/EntityCacheTagsTestBase.php index 3b382e1..6482093 100644 --- a/core/modules/system/src/Tests/Entity/EntityCacheTagsTestBase.php +++ b/core/modules/system/src/Tests/Entity/EntityCacheTagsTestBase.php @@ -10,6 +10,7 @@ use Drupal\Core\Cache\Cache; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface; +use Drupal\Core\Field\Plugin\Field\FieldWidget\OptionsWidgetBase; use Drupal\Core\Url; use Drupal\field\Entity\FieldStorageConfig; use Drupal\field\Entity\FieldConfig; @@ -244,7 +245,7 @@ protected function createReferenceTestEntities($referenced_entity) { 'target_bundles' => array( $referenced_entity->bundle() => $referenced_entity->bundle(), ), - 'sort' => array('field' => '_none'), + 'sort' => array('field' => OptionsWidgetBase::OPTIONS_EMPTY_OPTION), 'auto_create' => FALSE, ), ), diff --git a/core/modules/user/src/Plugin/EntityReferenceSelection/UserSelection.php b/core/modules/user/src/Plugin/EntityReferenceSelection/UserSelection.php index d766378..5fb2043 100644 --- a/core/modules/user/src/Plugin/EntityReferenceSelection/UserSelection.php +++ b/core/modules/user/src/Plugin/EntityReferenceSelection/UserSelection.php @@ -14,6 +14,7 @@ use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Session\AccountInterface; +use Drupal\Core\Field\Plugin\Field\FieldWidget\OptionsWidgetBase; use Drupal\user\RoleInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -85,7 +86,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta // Merge in default values. $selection_handler_settings += array( 'filter' => array( - 'type' => '_none', + 'type' => OptionsWidgetBase::OPTIONS_EMPTY_OPTION, ), 'include_anonymous' => TRUE, ); @@ -101,7 +102,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta '#type' => 'select', '#title' => $this->t('Filter by'), '#options' => array( - '_none' => $this->t('- None -'), + OptionsWidgetBase::OPTIONS_EMPTY_OPTION => $this->t('- None -'), 'role' => $this->t('User role'), ), '#ajax' => TRUE,