API page: https://api.drupal.org/api/drupal/core%21modules%21options%21options.mod...

As @dawehner_ pointed out that this cache_id is not good:)

  $cache_id = implode(':', array($entity->entityType(), $entity->bundle(), $field_definition->getFieldName()));

This cache_id doesn't involve with entity level, only entity type, bundle and field name. But in fact, this function's result could depend on parameter EntityInterface $entity potentially. See

    $function = $field_definition->getFieldSetting('allowed_values_function');
    // If $cacheable is FALSE, then the allowed values are not statically
    // cached. See options_test_dynamic_values_callback() for an example of
    // generating dynamic and uncached values.
    $cacheable = TRUE;
    if (!empty($function)) {
      $values = $function($field_definition, $entity, $cacheable);
    }

It needs entity to return value, but the cache_id doesn't count the entity identifier, so the dynamic feature for each entity wouldn't fly.

While there's an issue #2012130: Regression: Views integration for "list" field types is broken about whether we need this feature, we need to adjust the cache_id to make this feature work correctly. It depends on field_definition, if this field makes use of

$function = $field_definition->getFieldSetting('allowed_values_function');

we need to count the entity identifier, e.g., 'Uuid of this entity' into cache_id. Otherwise, it's ok to use current cache_id.

Comments

smiletrl’s picture

To better explain the cache flaw, here's an example.

An option field 'test_options' makes use of this dynamic options feature, it's definition could look like

    $this->field_name = 'test_options';
    entity_create('field_entity', array(
      'field_name' => $this->field_name,
      'type' => 'list_text',
      'cardinality' => 1,
      'settings' => array(
        'allowed_values_function' => 'options_test_dynamic_values_callback',
      ),
    ))->save();

Code comes from here

Let's assume there're two nodes. Both have node bundle 'article', and they have this field attached.
So, node_1 and node_2 will have different allowed options for this field. But see cache_id here, it won't count the second node_2, because cache_id is the same for node_1 and node_2. Consequently, this dynamic options feature won't fly.

smiletrl’s picture

Status: Active » Needs review
StatusFileSize
new855 bytes

Add a pacth.

Status: Needs review » Needs work

The last submitted patch, dynamic_options_cache_id-2037217-2.patch, failed testing.

smiletrl’s picture

Status: Needs work » Needs review
StatusFileSize
new857 bytes

Wierd, $entity->uuid will fail?

smiletrl’s picture

Issue tags: +Need tests
StatusFileSize
new892 bytes

Patch at #5 should fail.

This values should depend on the $field_definition, i.e., the field name too. New patch attached.

Need tests to cover options values and the dynamic values flaw.

smiletrl’s picture

This test patch is to show the dynamic options cache_id flaw.

smiletrl’s picture

StatusFileSize
new910 bytes
new3.68 KB

whoops, extra space.

smiletrl’s picture

Issue tags: -Need tests

Remove Needs test tag.

Status: Needs review » Needs work

The last submitted patch, dynamic_options-2037217-8-fix.patch, failed testing.

smiletrl’s picture

Status: Needs work » Needs review

#8: dynamic_options-2037217-8-fix.patch queued for re-testing.

drabik’s picture

Issue tags: -Needs reroll
StatusFileSize
new3.65 KB

rerolled

Status: Needs review » Needs work

The last submitted patch, 13: dynamic_options-2037217-12.patch, failed testing.

drabik’s picture

Issue tags: +Needs reroll
jlbellido’s picture

Status: Needs work » Needs review
StatusFileSize
new3.65 KB

Rerolled #8 again.

Status: Needs review » Needs work

The last submitted patch, 16: dynamic_options-2037217-16-fix.patch, failed testing.

jlbellido’s picture

Status: Needs work » Needs review
StatusFileSize
new3.88 KB
new1.02 KB

Changed
$this->entity_1->uri();
To
$this->entity_1->url();

Tests that was failing pass now locally. Lets try again.

sweetchuck’s picture

Issue tags: -Needs reroll

The patch #18 is applicable to the latest 8.x 0a8e34cf15f237c0672dd6ea7776d46393467ce1 Sat Mar 29 12:40:21 2014 +0100

andypost’s picture

Looks good, except:

+++ b/core/modules/options/options.module
@@ -64,7 +64,7 @@ function options_field_config_delete(FieldConfigInterface $field) {
-  $cache_id = implode(':', array($entity->getEntityTypeId(), $entity->bundle(), $field_definition->getName()));
+  $cache_id = implode(':', array($entity->getEntityTypeId(), $entity->bundle(), $field_definition->getName(), $entity->uuid()));

any reason to use uuid() here, suppose a ID is enough.

yched’s picture

There are places that need a list of allowed values without having a specific $entity available.
Example : building the options for a dropdown select form element for a Views filter - in this context we are not restricted to a specific bundle, so we can't even build a "fake" entity.

- The current options_allowed_values() function is already flawed because it assumes an $entity param will be present.
Long time since I looked at the issue, but that's probably what #2012130: Regression: Views integration for "list" field types is broken is about.

- The current code already has a mechanism to account for "how do we statically cache if the result of the allowed_values_function depends on the $entity" : it's the $cacheable boolean variable. If an $entity is present, and the allowed_values_function returns a result that depends on it, then it is its responsibility to set $cacheable to FALSE by ref before returning the result, so that options_allowed_values() doesn't cache it. I know it's only a static cache, but it can still have nasty effects on long-running drush scripts.

- Adding the $entity->uuid (if present) to the cache id is of no use. It does not ensure the cached results are correct, since the $entity values can change: its uuid will always be the same, but the entity is different, so the allowed_values_function results can potentially be different too, and the cached data is stale.

I'd tend to won't fix this, and stay with the current behavior : if an allowed_values_function returns a result that actually depends on the $entity, it needs to tell the caller not to cache the results.

Also, given the above, I don't think this qualifies as a bug ?

jhedstrom’s picture

Status: Needs review » Needs work
Issue tags: +Needs reroll

Reroll plus a bit of work given #21.

yched’s picture

Status: Needs work » Closed (works as designed)

I still stand by #21 - plus, given the work happening in #2238085: [regression] options_allowed_values() signature doesn't allow for Views filter configuration, I do think this is a won't fix.