Commit 4de09b6b authored by alexpott's avatar alexpott

Issue #2238085 by dawehner, yched, damiankloip, xjm, effulgentsia, vijaycs85,...

Issue #2238085 by dawehner, yched, damiankloip, xjm, effulgentsia, vijaycs85, fago, tim.plunkett, cilefen, pcambra: [regression] options_allowed_values() signature doesn't allow for Views filter configuration
parent f41585c8
......@@ -5,6 +5,9 @@
* Hooks provided by the Options module.
*/
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
/**
* Alters the list of options to be displayed for a field.
*
......@@ -32,3 +35,55 @@ function hook_options_list_alter(array &$options, array $context) {
$options['_none'] = t('== Empty ==');
}
}
/**
* Provides the allowed values for an options field or widget.
*
* Callback for options_allowed_values().
*
* @param \Drupal\Core\Field\FieldStorageDefinitionInterface $definition
* The field storage definition.
* @param \Drupal\Core\Entity\FieldableEntityInterface|NULL $entity
* (optional) A specific entity to use for either restricting the values or
* customizing the labels for particular bundles and entities. NULL when
* there is not a specific entity available, such as for Views filters.
* @param bool $cacheable
* (optional) 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. Defaults to TRUE.
*
* @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.
*
* @see options_allowed_values()
* @see options_test_allowed_values_callback()
* @see options_test_dynamic_values_callback()
*/
function callback_allowed_values_function(FieldStorageDefinitionInterface $definition, FieldableEntityInterface $entity = NULL, $cacheable = TRUE) {
if (isset($entity) && ($entity->bundle() == 'not_a_programmer')) {
$values = array(
'Group 1' => array(
1 => 'One',
),
'Group 2' => array(
2 => 'Two',
),
);
}
else {
$values = array(
'Group 1' => array(
0 => 'Zero',
),
'Group 2' => array(
1 => 'One',
),
);
}
return $values;
}
......@@ -5,9 +5,9 @@
* Defines selection, check box and radio button widgets for text and numeric fields.
*/
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Entity\Exception\FieldStorageDefinitionUpdateForbiddenException;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\field\FieldStorageConfigInterface;
......@@ -54,30 +54,41 @@ function options_field_storage_config_delete(FieldStorageConfigInterface $field_
* sanitized through \Drupal\Core\Field\AllowedTagsXssTrait::fieldFilterXss()
* before being displayed.
*
* @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
* The field definition.
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity object.
* @param \Drupal\Core\Field\FieldStorageDefinitionInterface $definition
* The field storage definition.
* @param \Drupal\Core\Entity\FieldableEntityInterface|NULL $entity
* (optional) The specific entity when this function is called from the
* context of a specific field on a specific entity. This allows custom
* 'allowed_values_function' callbacks to either restrict the values or
* customize the labels for particular bundles and entities. NULL when
* there is not a specific entity available, such as for Views filters.
*
* @return
* @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.
*
* @see callback_allowed_values_function()
*/
function options_allowed_values(FieldDefinitionInterface $field_definition, EntityInterface $entity) {
function options_allowed_values(FieldStorageDefinitionInterface $definition, FieldableEntityInterface $entity = NULL) {
$allowed_values = &drupal_static(__FUNCTION__, array());
$cache_id = implode(':', array($entity->getEntityTypeId(), $entity->bundle(), $field_definition->getName()));
$cache_keys = array($definition->getTargetEntityTypeId(), $definition->getName());
if ($entity) {
$cache_keys[] = 'entity';
}
$cache_id = implode(':', $cache_keys);
if (!isset($allowed_values[$cache_id])) {
$function = $field_definition->getSetting('allowed_values_function');
$function = $definition->getSetting('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);
$values = $function($definition, $entity, $cacheable);
}
else {
$values = $field_definition->getSetting('allowed_values');
$values = $definition->getSetting('allowed_values');
}
if ($cacheable) {
......
......@@ -34,21 +34,41 @@ class OptionsDefaultFormatter extends FormatterBase {
public function viewElements(FieldItemListInterface $items) {
$elements = array();
$entity = $items->getEntity();
$allowed_values = options_allowed_values($this->fieldDefinition, $entity);
// Only collect allowed options if there are actually items to display.
if ($items->count()) {
$provider = $items->getFieldDefinition()
->getFieldStorageDefinition()
->getOptionsProvider('value', $items->getEntity());
// Flatten the possible options, to support opt groups.
$options = $this->flattenOptions($provider->getPossibleOptions());
foreach ($items as $delta => $item) {
if (isset($allowed_values[$item->value])) {
$output = $this->fieldFilterXss($allowed_values[$item->value]);
foreach ($items as $delta => $item) {
$value = $item->value;
// If the stored value is in the current set of allowed values, display
// the associated label, otherwise just display the raw value.
$output = isset($options[$value]) ? $options[$value] : $value;
$elements[$delta] = array('#markup' => $this->fieldFilterXss($output));
}
else {
// If no match was found in allowed values, fall back to the key.
$output = $this->fieldFilterXss($item->value);
}
$elements[$delta] = array('#markup' => $output);
}
return $elements;
}
/**
* Flattens an array of allowed values.
*
* @param array $array
* A single or multidimensional array.
*
* @return array
* The flattened array.
*
* @todo Remove it once https://www.drupal.org/node/2392301 landed.
*/
protected function flattenOptions(array $array) {
$result = array();
array_walk_recursive($array, function($a, $b) use (&$result) { $result[$b] = $a; });
return $result;
}
}
......@@ -63,7 +63,7 @@ public function getSettableValues(AccountInterface $account = NULL) {
* {@inheritdoc}
*/
public function getSettableOptions(AccountInterface $account = NULL) {
$allowed_options = options_allowed_values($this->getFieldDefinition(), $this->getEntity());
$allowed_options = options_allowed_values($this->getFieldDefinition()->getFieldStorageDefinition(), $this->getEntity());
return $allowed_options;
}
......
<?php
/**
* @file
* Contains \Drupal\options\Tests\OptionsDynamicValuesApiTest.
*/
namespace Drupal\options\Tests;
/**
* 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 = array(
$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);
}
}
......@@ -28,11 +28,18 @@
*/
protected $entity;
/**
* The field storage.
*
* @var \Drupal\Core\Field\FieldStorageDefinitionInterface
*/
protected $fieldStorage;
protected function setUp() {
parent::setUp();
$this->field_name = 'test_options';
entity_create('field_storage_config', array(
$this->fieldStorage = entity_create('field_storage_config', array(
'field_name' => $this->field_name,
'entity_type' => 'entity_test_rev',
'type' => 'list_string',
......@@ -40,7 +47,9 @@ protected function setUp() {
'settings' => array(
'allowed_values_function' => 'options_test_dynamic_values_callback',
),
))->save();
));
$this->fieldStorage->save();
$this->field = entity_create('field_config', array(
'field_name' => $this->field_name,
'entity_type' => 'entity_test_rev',
......
......@@ -5,13 +5,15 @@
* Helper module for the List module tests.
*/
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
/**
* Allowed values callback.
*
* @see options_allowed_values().
*/
function options_test_allowed_values_callback(FieldDefinitionInterface $field_definition, EntityInterface $entity) {
function options_test_allowed_values_callback(FieldStorageDefinitionInterface $definition, FieldableEntityInterface $entity = NULL) {
$values = array(
'Group 1' => array(
0 => 'Zero',
......@@ -30,15 +32,25 @@ function options_test_allowed_values_callback(FieldDefinitionInterface $field_de
/**
* An entity-bound allowed values callback.
*
* @todo This function violates the recommendation in options_allowed_values()
* to return a list of all possible values in any context when $items is
* NULL. Since this is not yet used for testing Views integration, that is
* alright for now. Fix this in https://www.drupal.org/node/2012130.
*
* @see options_allowed_values().
*/
function options_test_dynamic_values_callback(FieldDefinitionInterface $field_definition, EntityInterface $entity, &$cacheable) {
$cacheable = FALSE;
$values = array(
$entity->label(),
$entity->url(),
$entity->uuid(),
$entity->bundle(),
);
function options_test_dynamic_values_callback(FieldStorageDefinitionInterface $definition, FieldableEntityInterface $entity = NULL, &$cacheable = NULL) {
$values = array();
if (isset($entity)) {
$cacheable = FALSE;
$values = array(
$entity->label(),
$entity->url(),
$entity->uuid(),
$entity->bundle(),
);
}
// We need the values of the entity as keys.
return array_combine($values, $values);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment