Problem/Motivation

Core option fields don't allow using predefined select list. One can use https://github.com/Realityloop/list_predefined_options to add the functionality which is an unoffical port of http://drupal.org/project/list_predefined_options.

It is a very generic functionality i.e. country list, states lists, timezones and language list.

Proposed resolution

Move https://github.com/Realityloop/list_predefined_options functionality to the core. It shouldn't have to be an experimental module.

Remaining tasks

  • Create Patch (WIP)
  • Update the docs with the new plugin type

User interface changes

None

API changes

The 'allowed_values_function' will be deprecated since its functionality is covered by the new plugin type.

Issue fork drupal-1909744

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

jibran’s picture

Issue tags: +Field API

Tagging 'Field API' as per @swentel suggestion.

swentel’s picture

Issue tags: -Field API

Removing tags for now (just to get focus on our personal issue list scraper)

swentel’s picture

jibran’s picture

Version: 8.0.x-dev » 8.1.x-dev

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.0-beta1 was released on March 2, 2016, which means new developments and disruptive changes should now be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

jibran’s picture

There is a D8 port now in #2635932-3: Drupal 8? now which is maintained at https://github.com/Realityloop/list_predefined_options.

joachim’s picture

Needs a summary update, as the Proposed resolution shouldn't be a hook :)

It should be fairly simple to add the D8 code I wrote to Options core module, IIRC it's mostly a plugin and a little bit of UI.

jibran’s picture

Title: Add list_predefined_options functionality to core » Allow adding predefined lists to the options fields
Issue summary: View changes
Issue tags: -Needs issue summary update

Is it better?

joachim’s picture

Yup, much! Thanks!

One question: should this be a separate modoule, or should the functionality be added to Options module?

jibran’s picture

Let's add it to options module.

joachim’s picture

I had another look at the the D8 port of list_predefined_options (at #2635932: Drupal 8?), and I see now that there are some changes that would be needed or desirable to bring it into core:

- rather than store the plugin ID in third party settings, we should instead add a new property ('predefined_options_plugin') to the schemas for the storage settings, eg field.storage_settings.list_integer
- options_allowed_values() should use the predefined_options_plugin setting if present to get the options. (basically, do the work of list_predefined_options_allowed_values() in my module code)
- the allowed_values_function system should be deprecated (the allowed_values_function property, and callback_allowed_values_function()). This is because the same thing can be accomplished with a plugin.
- list_predefined_options_form_field_storage_config_edit_form_builder() isn't necessary, since there's no longer a need to set the 'allowed_values_function' property.
- additionally, the 'US states' plugin should be removed IMO, as it's country-specific, and Drupal has an international audience.

Also, it might be an idea to consider the UI, since adding the elements in the actual field storage settings form rather than using hook_form_alter() means we could do something different, if it improved the usability of the form.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

d70rr3s’s picture

Status: Active » Needs review
FileSize
22.14 KB

Hi, I just found my self using the list_predefined_options port quite a lot and felt eager to see it in core. The attached patch ports the feature with the design notes from #12 also added some tests but still some tasks remaining. I put it on Needs review so once most of the patch get reviewed I will continue working on the remaining tasks.

d70rr3s’s picture

Issue summary: View changes

Took the lease of updating the issue summary.

Status: Needs review » Needs work

The last submitted patch, 17: 1909744-predefined-options-17.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

d70rr3s’s picture

Attached new patch with more tests, also fixed CS from bot and removed the @trigger_error that was making some tests to fail. Still needs work seems some tests keep failing. If is okay for maintainers this can be assigned to me.

d70rr3s’s picture

Seems that removing allowed_values_function from options.schema.yml is breaking some integration tests on other core's components. I just add it back and restore the field storage settings form element (the warning message still be shown) and the tests. I think I'll need some assistance here on how to proceed.

d70rr3s’s picture

d70rr3s’s picture

Status: Needs work » Needs review

Well seems this is working fine now putting it to Needs review.

d70rr3s’s picture

I've queue for another test round to check everything is working with latest codebase. @joachim if someone could review this since seems complete by your guidelines.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

yonailo’s picture

Hi,

I don't understand what the problem is with the current 'allowed_values_function' and what this issue adds that could not be done using the current 'allowed_values_function' functionality. Can you develop please ?

d70rr3s’s picture

There's none, this feature request is about replacing it with a new plugin type. The #1909744-21: Allow adding predefined lists to the options fields refers about BC, the allowed_values_function is used on tests outside the options module also other contrib modules may be using it to define their own options selectors. Please read the whole thread specially #1909744-12: Allow adding predefined lists to the options fields, @joachim describes the proposed solution. There is also a previous issue seeking this exact same feature #2305385: Convert "allowed_values_function" to a plugin.

Status: Needs review » Needs work

The last submitted patch, 22: 1909744-predefined-options-22.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

vsujeetkumar’s picture

Status: Needs work » Needs review
FileSize
31.04 KB

Re-roll patch created for 9.3.x.

Status: Needs review » Needs work

The last submitted patch, 32: 1909744-32.patch, failed testing. View results

vsujeetkumar’s picture

Status: Needs work » Needs review
FileSize
31.79 KB
4.64 KB

Fixed fail tests, Please have a look.

alvolvfdez’s picture

Rerolled for 9.2.x

joachim’s picture

Status: Needs review » Needs work

This is looking good! And the new hook has documentation -- great!

Mostly typos, but I do wonder whether we should use a proper metadata object instead of the old D7-era $cacheable boolean.

  1. +++ b/core/modules/options/options.api.php
    @@ -36,6 +36,23 @@ function hook_options_list_alter(array &$options, array $context) {
    +function hook_options_predefined_options_info_alter(&$definitions) {
    

    (Yay! Documentation!)

  2. +++ b/core/modules/options/src/Plugin/Field/FieldType/ListItemBase.php
    @@ -80,22 +103,37 @@ public function isEmpty() {
    -      '#access' => empty($allowed_values_function),
           '#element_validate' => [[static::class, 'validateAllowedValues']],
           '#field_has_data' => $has_data,
           '#field_name' => $this->getFieldDefinition()->getName(),
           '#entity_type' => $this->getEntity()->getEntityTypeId(),
           '#allowed_values' => $allowed_values,
    +      '#access' => empty($allowed_values_function),
    

    This line is moving for no reason. Since the patch needs work anyway, would be good to remove this change.

  3. +++ b/core/modules/options/src/Plugin/PredefinedOptionsPluginBase.php
    @@ -0,0 +1,14 @@
    +  // Add common methods and abstract methods for your plugin type here.
    

    Stray scaffolding code.

    In fact, we don't need this class since it's empty.

  4. +++ b/core/modules/options/src/Plugin/PredefinedOptionsPluginInterface.php
    @@ -0,0 +1,37 @@
    +   * Returns the of allowed values.
    

    Typo.

  5. +++ b/core/modules/options/src/Plugin/PredefinedOptionsPluginInterface.php
    @@ -0,0 +1,37 @@
    +   * @param bool &$cacheable
    

    I wonder if we should take this opportunity of a new system to change from this boolean $cacheable parameter to returning a proper cache metadata object.

  6. +++ b/core/modules/options/src/Plugin/PredefinedOptionsPluginInterface.php
    @@ -0,0 +1,37 @@
    +   *   returned was specifically adjusted for that entity and cannot not be
    

    'cannot not'

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

alvolvfdez’s picture

Reroll for 9.3.x.

Removed the lines where typing was added in some variables. In Drupal 9.3.0 they are already added. File: core/modules/options/tests/src/Functional/OptionsFieldUITest.php

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

BryanGullan’s picture

Re-rolled patch for 9.5.x

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

BramDriesen made their first commit to this issue’s fork.

BramDriesen’s picture

#36 Still needs to be addressed.

BramDriesen’s picture

1 (nothing to do), 2, 4 and 6 are fixed.

For 3, not really sure what's going on, as the interface is defining getAllowedValues. I guess we could add a stub instead of removing it?
For 5, Still a to-do, currently too late for me to start on that.

Lendude’s picture

Sounds like a good improvement over callbacks!

Some observations:

  1. +++ b/core/modules/options/config/schema/options.schema.yml
    @@ -17,6 +17,9 @@ field.storage_settings.list_integer:
    +    predefined_options_plugin:
    +      type: string
    
    @@ -50,6 +53,9 @@ field.storage_settings.list_float:
    +    predefined_options_plugin:
    +      type: string
    
    @@ -83,6 +89,9 @@ field.storage_settings.list_string:
    +    predefined_options_plugin:
    +      type: string
    

    This needs an upgrade path to set the empty value

  2. +++ b/core/modules/options/options.api.php
    @@ -36,6 +36,23 @@ function hook_options_list_alter(array &$options, array $context) {
    +function hook_options_predefined_options_info_alter(&$definitions) {
    

    I don't think this currently has test coverage?

  3. +++ b/core/modules/options/options.api.php
    @@ -78,6 +95,11 @@ function hook_options_list_alter(array &$options, array $context) {
    + * @deprecated in drupal:9.3.0 and is removed from drupal:10.0.0. Once the
    + *   predefined options plugin feature is completed.
    + *
    + * @see https://www.drupal.org/project/drupal/issues/1909744
    

    Versions need updating and needs to point to a Change record and not this issue

  4. +++ b/core/modules/options/options.module
    @@ -80,12 +81,30 @@ function options_allowed_values(FieldStorageDefinitionInterface $definition, Fie
    +      catch (\Exception $e) {
    +        // Fail silently if the plugin does not exists or cannot be instantiated.
    +        watchdog_exception('options', $e);
    +        return [];
    +      }
    

    Do we usually fail silently on these? I think in other instances we just let it fail hard, something is seriously wrong if a plugin disappears.

  5. +++ b/core/modules/options/options.module
    @@ -80,12 +81,30 @@ function options_allowed_values(FieldStorageDefinitionInterface $definition, Fie
    +      watchdog_exception('options', new \RuntimeException(t("The use of 'allowed_values_function' is deprecated, use :class plugins instead", [
    +        ':class' => PredefinedOptions::class,
    +      ])));
    

    An indication of which field is using this might help people track down what they need to update? And why the watchdog_exception and not just a trigger_error("bla bla", E_USER_DEPRECATED);?

  6. +++ b/core/modules/options/src/Annotation/PredefinedOptions.php
    @@ -0,0 +1,33 @@
    +  public $id;
    

    Add a type hint

  7. +++ b/core/modules/options/src/Annotation/PredefinedOptions.php
    @@ -0,0 +1,33 @@
    +  public $label;
    

    add a type hint

  8. +++ b/core/modules/options/src/Plugin/Field/FieldType/ListItemBase.php
    @@ -106,6 +144,36 @@ public function storageSettingsForm(array &$form, FormStateInterface $form_state
    +    elseif (!empty($allowed_values_function = $this->getSetting('allowed_values_function'))) {
    

    Setting vars in ifs I think we try to avoid (it's pretty clumsy to read)

  9. +++ b/core/modules/options/src/Plugin/Field/FieldType/ListItemBase.php
    @@ -329,4 +397,24 @@ protected static function castAllowedValue($value) {
    +      $this->messenger()
    +        ->addWarning($this->t('The use of callback functions is deprecated. Please replace %function function with a plugin. :link.', [
    

    Why not just trigger_error("bla bla", E_USER_DEPRECATED);

  10. +++ b/core/modules/options/src/Plugin/Options/Timezones.php
    @@ -0,0 +1,26 @@
    +namespace Drupal\options\Plugin\Options;
    ...
    +class Timezones extends PredefinedOptionsPluginBase {
    

    Are we sure we want to supply this for all installs of Drupal, it feels like a good test case to use, but I'd say it should probably be in a test module. I don't think the need for this is in the '80% of all sites' category.

  11. +++ b/core/modules/options/src/Plugin/PredefinedOptionsPluginInterface.php
    @@ -0,0 +1,37 @@
    +   * @param bool &$cacheable
    +   *   (optional) If an $entity is provided, the $cacheable parameter should be
    +   *   modified by reference and set to FALSE if the set of allowed values
    +   *   returned was specifically adjusted for that entity and cannot not be
    +   *   reused for other entities. Defaults to TRUE.
    

    Do we need test coverage for this?

  12. +++ b/core/modules/options/src/Plugin/PredefinedOptionsPluginInterface.php
    @@ -0,0 +1,37 @@
    +   * @return array
    +   *   The array of allowed values. Keys of the array are the raw stored values
    +   *   (number or text), values of the array are the display labels. If $entity
    +   *   is NULL, you should return the list of all the possible allowed values
    +   *   in any context so that other code (e.g. Views filters) can support the
    +   *   allowed values for all possible entities and bundles.
    

    We need a test for this I feel, so use the options list in the Views UI and make sure it works

  13. +++ b/core/modules/options/tests/options_test/src/Plugin/Options/PredefinedOptionsTestPlugin.php
    @@ -0,0 +1,37 @@
    +    if ($entity === NULL) {
    +      return [];
    +    }
    ...
    +    $values = [
    +      $entity->label(),
    +      $entity->toUrl()->toString(),
    +      $entity->uuid(),
    +      $entity->bundle(),
    +    ];
    

    This does exactly the opposite of what the method docblock says you should do when $entity is NULL, that sounds like a bad example to set

  14. +++ b/core/modules/options/tests/src/Functional/OptionsFieldUITest.php
    @@ -333,6 +352,35 @@ public function assertAllowedValuesInput(string $input_string, $result, string $
    +  public function assertPredefinedOptionsInput($plugin_id, $result, $message) {
    

    We tend not to set messages for assertions anymore so we can probably leave that out

  15. +++ b/core/modules/options/tests/src/Functional/OptionsFieldUITest.php
    @@ -333,6 +352,35 @@ public function assertAllowedValuesInput(string $input_string, $result, string $
    +      self::assertEquals($plugin->getAllowedValues($field_storage), $result, $message);
    

    We use $this and not self:: for assertions

  16. +++ b/core/modules/options/tests/src/Functional/OptionsPredefinedOptionsPluginTest.php
    @@ -0,0 +1,34 @@
    +namespace Drupal\Tests\options\Functional;
    ...
    +class OptionsPredefinedOptionsPluginTest extends OptionsPredefinedOptionsTestBase {
    

    This is not using the browser I think? so does this need to be a functional test or can it be a kernel test?

  17. +++ b/core/modules/options/tests/src/Functional/OptionsPredefinedOptionsPluginTest.php
    @@ -0,0 +1,34 @@
    +    $this->assertEquals($values, []);
    ...
    +    $this->assertEquals($values, $expected_values);
    

    Expected values go first

  18. +++ b/core/modules/options/tests/src/Functional/OptionsPredefinedOptionsValidationTest.php
    @@ -0,0 +1,44 @@
    +    $allowed_values = $this->plugin->getAllowedValues($this->fieldStorage, $this->entity);
    +    foreach ($allowed_values as $key => $value) {
    

    Add a check that $allowed_values is not empty, currently if it is empty, the test passes

  19. +++ b/core/modules/options/tests/src/Functional/OptionsSelectPredefinedOptionsTest.php
    @@ -0,0 +1,41 @@
    +        self::assertNotEmpty(array_search($value, $values, TRUE));
    

    We use $this not self:: for assertions

Lendude’s picture

Oh forgot to refresh and missed the MR, so some of that might have been addressed already!

BramDriesen’s picture

Actually not 😉 Think all your comments still apply. Although the deprecated watchdog_exceptions are replaced with the logger API.

dpi’s picture

We have another issue for using backed enums as a form of predefined list: #3249599: Add support for PHP 8.1 Backed Enums in Select, Checkboxes, Radio elements

Can we update/refocus this issue so it specifically outlines this is a plugin based solution?

Bonus for why plugin based solution is worthwhile alongside the enum solution (presumably dynamism?)

I understand allowed_values_function is due to be deprecated by this issue, it would be ideal to have a solution compatible with both plugin and enum solutions simultaneously.

joachim’s picture

I've made a D9/10 release of https://www.drupal.org/project/list_predefined_options.

#3249599: Add support for PHP 8.1 Backed Enums in Select, Checkboxes, Radio elements is not the same as this issue -- it's operating at the FormAPI level. This issue is at the FieldAPI level.

> Bonus for why plugin based solution is worthwhile alongside the enum solution (presumably dynamism?)

Dynamism is one. That would include things like being able to depend on other Drupal components, e.g. #1412946: Allow Views to be used for predefined lists. Reusability is another.

> it would be ideal to have a solution compatible with both plugin and enum solutions simultaneously.

Define a plugin which returns an enum.

asanchezs’s picture

Patch for Drupal 10.2.x