Skip to content
Snippets Groups Projects
Commit 5909b03b authored by Alex Pott's avatar Alex Pott
Browse files

Issue #2169983 by plopesc, yched: Move type-specific logic from ListItemBase...

Issue #2169983 by plopesc, yched: Move type-specific logic from ListItemBase to the appropriate subclass.
parent bbe2af1a
No related branches found
No related tags found
2 merge requests!7452Issue #1797438. HTML5 validation is preventing form submit and not fully...,!789Issue #3210310: Adjust Database API to remove deprecated Drupal 9 code in Drupal 10
...@@ -7,7 +7,11 @@ ...@@ -7,7 +7,11 @@
namespace Drupal\options\Plugin\Field\FieldType; namespace Drupal\options\Plugin\Field\FieldType;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemBase;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\TypedData\AllowedValuesInterface;
use Drupal\Core\TypedData\DataDefinition; use Drupal\Core\TypedData\DataDefinition;
/** /**
...@@ -15,7 +19,6 @@ ...@@ -15,7 +19,6 @@
* *
* @FieldType( * @FieldType(
* id = "list_boolean", * id = "list_boolean",
* module = "options",
* label = @Translation("Boolean"), * label = @Translation("Boolean"),
* description = @Translation("This field stores simple on/off or yes/no options."), * description = @Translation("This field stores simple on/off or yes/no options."),
* default_widget = "options_buttons", * default_widget = "options_buttons",
...@@ -26,30 +29,132 @@ ...@@ -26,30 +29,132 @@
* } * }
* ) * )
*/ */
class ListBooleanItem extends ListItemBase { class ListBooleanItem extends FieldItemBase implements AllowedValuesInterface {
/**
* {@inheritdoc}
*/
public function getPossibleValues(AccountInterface $account = NULL) {
return array_keys($this->getSettableOptions($account));
}
/**
* {@inheritdoc}
*/
public function getPossibleOptions(AccountInterface $account = NULL) {
return $this->getSettableOptions($account);
}
/**
* {@inheritdoc}
*/
public function getSettableValues(AccountInterface $account = NULL) {
return array_keys($this->getSettableOptions($account));
}
/**
* {@inheritdoc}
*/
public function getSettableOptions(AccountInterface $account = NULL) {
return options_allowed_values($this->getFieldDefinition(), $this->getEntity());
}
/**
* {@inheritdoc}
*/
public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
$properties['value'] = DataDefinition::create('boolean')
->setLabel(t('Boolean value'));
return $properties;
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public static function schema(FieldDefinitionInterface $field_definition) { public static function schema(FieldDefinitionInterface $field_definition) {
return parent::schema($field_definition) + array( return array(
'columns' => array( 'columns' => array(
'value' => array( 'value' => array(
'type' => 'int', 'type' => 'int',
'not null' => FALSE, 'not null' => FALSE,
), ),
), ),
'indexes' => array(
'value' => array('value'),
),
); );
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { public function isEmpty() {
$properties['value'] = DataDefinition::create('boolean') return empty($this->value) && (string) $this->value !== '0';
->setLabel(t('Boolean value')); }
return $properties; /**
* {@inheritdoc}
*/
public function settingsForm(array $form, array &$form_state, $has_data) {
$allowed_values = $this->getSetting('allowed_values');
$allowed_values_function = $this->getSetting('allowed_values_function');
$values = $allowed_values;
$off_value = array_shift($values);
$on_value = array_shift($values);
$element['allowed_values'] = array(
'#type' => 'value',
'#description' => '',
'#value_callback' => array(get_class($this), 'optionsBooleanAllowedValues'),
'#access' => empty($allowed_values_function),
);
$element['allowed_values']['on'] = array(
'#type' => 'textfield',
'#title' => t('On value'),
'#default_value' => $on_value,
'#required' => FALSE,
'#description' => t('If left empty, "1" will be used.'),
// Change #parents to make sure the element is not saved into field
// settings.
'#parents' => array('on'),
);
$element['allowed_values']['off'] = array(
'#type' => 'textfield',
'#title' => t('Off value'),
'#default_value' => $off_value,
'#required' => FALSE,
'#description' => t('If left empty, "0" will be used.'),
// Change #parents to make sure the element is not saved into field
// settings.
'#parents' => array('off'),
);
// Link the allowed value to the on / off elements to prepare for the rare
// case of an alter changing #parents.
$element['allowed_values']['#on_parents'] = &$element['allowed_values']['on']['#parents'];
$element['allowed_values']['#off_parents'] = &$element['allowed_values']['off']['#parents'];
$element['allowed_values_function'] = array(
'#type' => 'item',
'#title' => t('Allowed values list'),
'#markup' => t('The value of this field is being determined by the %function function and may not be changed.', array('%function' => $allowed_values_function)),
'#access' => !empty($allowed_values_function),
'#value' => $allowed_values_function,
);
return $element;
}
/**
* Form element #value_callback: assembles the allowed values for 'boolean'
* fields.
*/
public static function optionsBooleanAllowedValues($element, $input, $form_state) {
$on = NestedArray::getValue($form_state['input'], $element['#on_parents']);
$off = NestedArray::getValue($form_state['input'], $element['#off_parents']);
return array($off, $on);
} }
} }
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
* *
* @FieldType( * @FieldType(
* id = "list_float", * id = "list_float",
* module = "options",
* label = @Translation("List (float)"), * label = @Translation("List (float)"),
* description = @Translation("This field stores float values from a list of allowed 'value => label' pairs, i.e. 'Fraction': 0 => 0, .25 => 1/4, .75 => 3/4, 1 => 1."), * description = @Translation("This field stores float values from a list of allowed 'value => label' pairs, i.e. 'Fraction': 0 => 0, .25 => 1/4, .75 => 3/4, 1 => 1."),
* default_widget = "options_select", * default_widget = "options_select",
...@@ -28,28 +27,71 @@ ...@@ -28,28 +27,71 @@
*/ */
class ListFloatItem extends ListItemBase { class ListFloatItem extends ListItemBase {
/**
* {@inheritdoc}
*/
public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
$properties['value'] = DataDefinition::create('float')
->setLabel(t('Float value'));
return $properties;
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public static function schema(FieldDefinitionInterface $field_definition) { public static function schema(FieldDefinitionInterface $field_definition) {
return parent::schema($field_definition) + array( return array(
'columns' => array( 'columns' => array(
'value' => array( 'value' => array(
'type' => 'float', 'type' => 'float',
'not null' => FALSE, 'not null' => FALSE,
), ),
), ),
'indexes' => array(
'value' => array('value'),
),
); );
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { protected function allowedValuesDescription() {
$properties['value'] = DataDefinition::create('float') $description = '<p>' . t('The possible values this field can contain. Enter one value per line, in the format key|label.');
->setLabel(t('Float value')); $description .= '<br/>' . t('The key is the stored value, and must be numeric. The label will be used in displayed values and edit forms.');
$description .= '<br/>' . t('The label is optional: if a line contains a single number, it will be used as key and label.');
$description .= '<br/>' . t('Lists of labels are also accepted (one label per line), only if the field does not hold any values yet. Numeric keys will be automatically generated from the positions in the list.');
$description .= '</p>';
$description .= '<p>' . t('Allowed HTML tags in labels: @tags', array('@tags' => _field_filter_xss_display_allowed_tags())) . '</p>';
return $description;
}
return $properties; /**
* {@inheritdoc}
*/
protected static function extractAllowedValues($string, $has_data) {
$values = parent::extractAllowedValues($string, $has_data);
if ($values) {
$keys = array_keys($values);
$labels = array_values($values);
$keys = array_map(function ($key) {
// Float keys are represented as strings and need to be disambiguated
// ('.5' is '0.5').
return is_numeric($key) ? (string) (float) $key : $key;
}, $keys);
return array_combine($keys, $labels);
}
}
/**
* {@inheritdoc}
*/
protected static function validateAllowedValue($option) {
if (!is_numeric($option)) {
return t('Allowed values list: each key must be a valid integer or decimal.');
}
} }
} }
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
* *
* @FieldType( * @FieldType(
* id = "list_integer", * id = "list_integer",
* module = "options",
* label = @Translation("List (integer)"), * label = @Translation("List (integer)"),
* description = @Translation("This field stores integer values from a list of allowed 'value => label' pairs, i.e. 'Lifetime in days': 1 => 1 day, 7 => 1 week, 31 => 1 month."), * description = @Translation("This field stores integer values from a list of allowed 'value => label' pairs, i.e. 'Lifetime in days': 1 => 1 day, 7 => 1 week, 31 => 1 month."),
* default_widget = "options_select", * default_widget = "options_select",
...@@ -28,28 +27,53 @@ ...@@ -28,28 +27,53 @@
*/ */
class ListIntegerItem extends ListItemBase { class ListIntegerItem extends ListItemBase {
/**
* {@inheritdoc}
*/
public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
$properties['value'] = DataDefinition::create('integer')
->setLabel(t('Integer value'));
return $properties;
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public static function schema(FieldDefinitionInterface $field_definition) { public static function schema(FieldDefinitionInterface $field_definition) {
return parent::schema($field_definition) + array( return array(
'columns' => array( 'columns' => array(
'value' => array( 'value' => array(
'type' => 'int', 'type' => 'int',
'not null' => FALSE, 'not null' => FALSE,
), ),
), ),
'indexes' => array(
'value' => array('value'),
),
); );
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { protected function allowedValuesDescription() {
$properties['value'] = DataDefinition::create('integer') $description = '<p>' . t('The possible values this field can contain. Enter one value per line, in the format key|label.');
->setLabel(t('Integer value')); $description .= '<br/>' . t('The key is the stored value, and must be numeric. The label will be used in displayed values and edit forms.');
$description .= '<br/>' . t('The label is optional: if a line contains a single number, it will be used as key and label.');
$description .= '<br/>' . t('Lists of labels are also accepted (one label per line), only if the field does not hold any values yet. Numeric keys will be automatically generated from the positions in the list.');
$description .= '</p>';
$description .= '<p>' . t('Allowed HTML tags in labels: @tags', array('@tags' => _field_filter_xss_display_allowed_tags())) . '</p>';
return $description;
}
return $properties; /**
* {@inheritdoc}
*/
protected static function validateAllowedValue($option) {
if (!preg_match('/^-?\d+$/', $option)) {
return t('Allowed values list: keys must be integers.');
}
} }
} }
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
namespace Drupal\options\Plugin\Field\FieldType; namespace Drupal\options\Plugin\Field\FieldType;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemBase; use Drupal\Core\Field\FieldItemBase;
use Drupal\Core\Session\AccountInterface; use Drupal\Core\Session\AccountInterface;
use Drupal\Core\TypedData\AllowedValuesInterface; use Drupal\Core\TypedData\AllowedValuesInterface;
...@@ -55,95 +54,31 @@ public function getSettableOptions(AccountInterface $account = NULL) { ...@@ -55,95 +54,31 @@ public function getSettableOptions(AccountInterface $account = NULL) {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public static function schema(FieldDefinitionInterface $field_definition) { public function isEmpty() {
return array( return empty($this->value) && (string) $this->value !== '0';
'indexes' => array(
'value' => array('value'),
),
);
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function settingsForm(array $form, array &$form_state, $has_data) { public function settingsForm(array $form, array &$form_state, $has_data) {
// @todo Move type-specific logic to the type-specific subclass:
// https://drupal.org/node/2169983.
$field_type = $this->getFieldDefinition()->getType();
$allowed_values = $this->getSetting('allowed_values'); $allowed_values = $this->getSetting('allowed_values');
$allowed_values_function = $this->getSetting('allowed_values_function'); $allowed_values_function = $this->getSetting('allowed_values_function');
if (in_array($field_type, array('list_integer', 'list_float', 'list_text'))) {
$element['allowed_values'] = array( $element['allowed_values'] = array(
'#type' => 'textarea', '#type' => 'textarea',
'#title' => t('Allowed values list'), '#title' => t('Allowed values list'),
'#default_value' => $this->allowedValuesString($allowed_values), '#default_value' => $this->allowedValuesString($allowed_values),
'#rows' => 10, '#rows' => 10,
'#element_validate' => array(array($this, 'validateAllowedValues')),
'#field_has_data' => $has_data,
'#access' => empty($allowed_values_function), '#access' => empty($allowed_values_function),
'#element_validate' => array(array(get_class($this), 'validateAllowedValues')),
'#field_has_data' => $has_data,
'#field_name' => $this->getFieldDefinition()->getName(),
'#entity_type' => $this->getEntity()->getEntityTypeId(),
'#allowed_values' => $allowed_values,
); );
$description = '<p>' . t('The possible values this field can contain. Enter one value per line, in the format key|label.'); $element['allowed_values']['#description'] = $this->allowedValuesDescription();
if ($field_type == 'list_integer' || $field_type == 'list_float') {
$description .= '<br/>' . t('The key is the stored value, and must be numeric. The label will be used in displayed values and edit forms.');
$description .= '<br/>' . t('The label is optional: if a line contains a single number, it will be used as key and label.');
$description .= '<br/>' . t('Lists of labels are also accepted (one label per line), only if the field does not hold any values yet. Numeric keys will be automatically generated from the positions in the list.');
}
else {
$description .= '<br/>' . t('The key is the stored value. The label will be used in displayed values and edit forms.');
$description .= '<br/>' . t('The label is optional: if a line contains a single string, it will be used as key and label.');
}
$description .= '</p>';
$element['allowed_values']['#description'] = $description;
}
elseif ($field_type == 'list_boolean') {
$values = $allowed_values;
$off_value = array_shift($values);
$on_value = array_shift($values);
$element['allowed_values'] = array(
'#type' => 'value',
'#description' => '',
'#value_callback' => 'options_field_settings_form_value_boolean_allowed_values',
'#access' => empty($allowed_values_function),
);
$element['allowed_values']['on'] = array(
'#type' => 'textfield',
'#title' => t('On value'),
'#default_value' => $on_value,
'#required' => FALSE,
'#description' => t('If left empty, "1" will be used.'),
// Change #parents to make sure the element is not saved into field
// settings.
'#parents' => array('on'),
);
$element['allowed_values']['off'] = array(
'#type' => 'textfield',
'#title' => t('Off value'),
'#default_value' => $off_value,
'#required' => FALSE,
'#description' => t('If left empty, "0" will be used.'),
// Change #parents to make sure the element is not saved into field
// settings.
'#parents' => array('off'),
);
// Link the allowed value to the on / off elements to prepare for the rare
// case of an alter changing #parents.
$element['allowed_values']['#on_parents'] = &$element['allowed_values']['on']['#parents'];
$element['allowed_values']['#off_parents'] = &$element['allowed_values']['off']['#parents'];
// Provide additional information about how to format allowed_values
// of a boolean field for use by a single on/off checkbox widget. Since
// the widget might not have been selected yet, can be changed independently
// of this form, and can vary by form mode, we display this information
// regardless of current widget selection.
$element['allowed_values']['#description'] .= '<p>' . t("For a 'single on/off checkbox' widget, define the 'off' value first, then the 'on' value in the <strong>Allowed values</strong> section. Note that the checkbox will be labeled with the label of the 'on' value.") . '</p>';
}
$element['allowed_values']['#description'] .= '<p>' . t('Allowed HTML tags in labels: @tags', array('@tags' => _field_filter_xss_display_allowed_tags())) . '</p>';
$element['allowed_values_function'] = array( $element['allowed_values_function'] = array(
'#type' => 'item', '#type' => 'item',
...@@ -157,39 +92,26 @@ public function settingsForm(array $form, array &$form_state, $has_data) { ...@@ -157,39 +92,26 @@ public function settingsForm(array $form, array &$form_state, $has_data) {
} }
/** /**
* Generates a string representation of an array of 'allowed values'. * Provides the field type specific allowed values form element #description.
*
* This string format is suitable for edition in a textarea.
*
* @param array $values
* An array of values, where array keys are values and array values are
* labels.
* *
* @return string * @return string
* The string representation of the $values array: * The field type allowed values form specific description.
* - Values are separated by a carriage return.
* - Each value is in the format "value|label" or "value".
*/ */
protected function allowedValuesString($values) { abstract protected function allowedValuesDescription();
$lines = array();
foreach ($values as $key => $value) {
$lines[] = "$key|$value";
}
return implode("\n", $lines);
}
/** /**
* Element validate callback; check that the entered values are valid. * #element_validate callback for options field allowed values.
*
* @param $element
* An associative array containing the properties and children of the
* generic form element.
* @param $form_state
* The $form_state array for the form this element belongs to.
*
* @see form_process_pattern()
*/ */
public function validateAllowedValues($element, &$form_state) { public static function validateAllowedValues($element, &$form_state) {
// @todo Move type-specific logic to the type-specific subclass: $values = static::extractAllowedValues($element['#value'], $element['#field_has_data']);
// https://drupal.org/node/2169983.
$field_type = $this->getFieldDefinition()->getType();
$has_data = $element['#field_has_data'];
$generate_keys = ($field_type == 'list_integer' || $field_type == 'list_float') && !$has_data;
$values = $this->extractAllowedValues($element['#value'], $generate_keys);
if (!is_array($values)) { if (!is_array($values)) {
\Drupal::formBuilder()->setError($element, $form_state, t('Allowed values list: invalid input.')); \Drupal::formBuilder()->setError($element, $form_state, t('Allowed values list: invalid input.'));
...@@ -197,54 +119,38 @@ public function validateAllowedValues($element, &$form_state) { ...@@ -197,54 +119,38 @@ public function validateAllowedValues($element, &$form_state) {
else { else {
// Check that keys are valid for the field type. // Check that keys are valid for the field type.
foreach ($values as $key => $value) { foreach ($values as $key => $value) {
if ($field_type == 'list_integer' && !preg_match('/^-?\d+$/', $key)) { if ($error = static::validateAllowedValue($key)) {
\Drupal::formBuilder()->setError($element, $form_state, t('Allowed values list: keys must be integers.')); \Drupal::formBuilder()->setError($element, $form_state, $error);
break;
}
if ($field_type == 'list_float' && !is_numeric($key)) {
\Drupal::formBuilder()->setError($element, $form_state, t('Allowed values list: each key must be a valid integer or decimal.'));
break;
}
elseif ($field_type == 'list_text' && drupal_strlen($key) > 255) {
\Drupal::formBuilder()->setError($element, $form_state, t('Allowed values list: each key must be a string at most 255 characters long.'));
break; break;
} }
} }
// Prevent removing values currently in use. // Prevent removing values currently in use.
if ($has_data) { if ($element['#field_has_data']) {
$lost_keys = array_diff(array_keys($this->getSetting('allowed_values')), array_keys($values)); $lost_keys = array_diff(array_keys($element['#allowed_values']), array_keys($values));
if (_options_values_in_use($this->getEntity()->getEntityTypeId(), $this->getFieldDefinition()->getName(), $lost_keys)) { if (_options_values_in_use($element['#entity_type'], $element['#field_name'], $lost_keys)) {
\Drupal::formBuilder()->setError($element, $form_state, t('Allowed values list: some values are being removed while currently in use.')); \Drupal::formBuilder()->setError($element, $form_state, t('Allowed values list: some values are being removed while currently in use.'));
} }
} }
form_set_value($element, $values, $form_state); \Drupal::formBuilder()->setValue($element, $values, $form_state);
} }
} }
/** /**
* Parses a string of 'allowed values' into an array. * Extracts the allowed values array from the allowed_values element.
* *
* @param string $string * @param string $string
* The list of allowed values in string format described in * The raw string to extract values from.
* \Drupal\options\Plugin\Field\FieldType\ListItemBase::allowedValuesString(). * @param bool $has_data
* @param bool $generate_keys * The current field already has data inserted or not.
* Boolean value indicating whether to generate keys based on the position
* of the value if a key is not manually specified, and if the value cannot
* be used as a key. This should only be TRUE for fields of type
* 'list_number'.
* *
* @return array * @return array|null
* The array of extracted key/value pairs, or NULL if the string is invalid. * The array of extracted key/value pairs, or NULL if the string is invalid.
* *
* @see \Drupal\options\Plugin\Field\FieldType\ListItemBase::allowedValuesString() * @see \Drupal\options\Plugin\Field\FieldType\ListTextItem::allowedValuesString()
*/ */
protected function extractAllowedValues($string, $generate_keys) { protected static function extractAllowedValues($string, $has_data) {
// @todo Move type-specific logic to the type-specific subclass:
// https://drupal.org/node/2169983.
$field_type = $this->getFieldDefinition()->getType();
$values = array(); $values = array();
$list = explode("\n", $string); $list = explode("\n", $string);
...@@ -253,8 +159,6 @@ protected function extractAllowedValues($string, $generate_keys) { ...@@ -253,8 +159,6 @@ protected function extractAllowedValues($string, $generate_keys) {
$generated_keys = $explicit_keys = FALSE; $generated_keys = $explicit_keys = FALSE;
foreach ($list as $position => $text) { foreach ($list as $position => $text) {
$value = $key = FALSE;
// Check for an explicit key. // Check for an explicit key.
$matches = array(); $matches = array();
if (preg_match('/(.*)\|(.*)/', $text, $matches)) { if (preg_match('/(.*)\|(.*)/', $text, $matches)) {
...@@ -263,16 +167,13 @@ protected function extractAllowedValues($string, $generate_keys) { ...@@ -263,16 +167,13 @@ protected function extractAllowedValues($string, $generate_keys) {
$value = trim($matches[2]); $value = trim($matches[2]);
$explicit_keys = TRUE; $explicit_keys = TRUE;
} }
// Otherwise see if we can use the value as the key. Detecting true integer // Otherwise see if we can use the value as the key.
// strings takes a little trick. elseif (!static::validateAllowedValue($text)) {
elseif ($field_type == 'list_text'
|| ($field_type == 'list_float' && is_numeric($text))
|| ($field_type == 'list_integer' && is_numeric($text) && (float) $text == intval($text))) {
$key = $value = $text; $key = $value = $text;
$explicit_keys = TRUE; $explicit_keys = TRUE;
} }
// Otherwise see if we can generate a key from the position. // Otherwise see if we can generate a key from the position.
elseif ($generate_keys) { elseif (!$has_data) {
$key = (string) $position; $key = (string) $position;
$value = $text; $value = $text;
$generated_keys = TRUE; $generated_keys = TRUE;
...@@ -281,12 +182,6 @@ protected function extractAllowedValues($string, $generate_keys) { ...@@ -281,12 +182,6 @@ protected function extractAllowedValues($string, $generate_keys) {
return; return;
} }
// Float keys are represented as strings and need to be disambiguated
// ('.5' is '0.5').
if ($field_type == 'list_float' && is_numeric($key)) {
$key = (string) (float) $key;
}
$values[$key] = $value; $values[$key] = $value;
} }
...@@ -299,11 +194,36 @@ protected function extractAllowedValues($string, $generate_keys) { ...@@ -299,11 +194,36 @@ protected function extractAllowedValues($string, $generate_keys) {
} }
/** /**
* {@inheritdoc} * Checks whether a candidate allowed value is valid.
*
* @param string $option
* The option value entered by the user.
*
* @return string
* The error message if the specified value is invalid, NULL otherwise.
*/ */
public function isEmpty() { protected static function validateAllowedValue($option) { }
$value = $this->get('value')->getValue();
return empty($value) && (string) $value !== '0'; /**
* Generates a string representation of an array of 'allowed values'.
*
* This string format is suitable for edition in a textarea.
*
* @param array $values
* An array of values, where array keys are values and array values are
* labels.
*
* @return string
* The string representation of the $values array:
* - Values are separated by a carriage return.
* - Each value is in the format "value|label" or "value".
*/
protected function allowedValuesString($values) {
$lines = array();
foreach ($values as $key => $value) {
$lines[] = "$key|$value";
}
return implode("\n", $lines);
} }
} }
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
* *
* @FieldType( * @FieldType(
* id = "list_text", * id = "list_text",
* module = "options",
* label = @Translation("List (text)"), * label = @Translation("List (text)"),
* description = @Translation("This field stores text values from a list of allowed 'value => label' pairs, i.e. 'US States': IL => Illinois, IA => Iowa, IN => Indiana."), * description = @Translation("This field stores text values from a list of allowed 'value => label' pairs, i.e. 'US States': IL => Illinois, IA => Iowa, IN => Indiana."),
* default_widget = "options_select", * default_widget = "options_select",
...@@ -28,11 +27,23 @@ ...@@ -28,11 +27,23 @@
*/ */
class ListTextItem extends ListItemBase { class ListTextItem extends ListItemBase {
/**
* {@inheritdoc}
*/
public static function propertyDefinitions(FieldDefinitionInterface $field_definition) {
$constraints = array('Length' => array('max' => 255));
$properties['value'] = DataDefinition::create('string')
->setLabel(t('Text value'))
->setConstraints($constraints);
return $properties;
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public static function schema(FieldDefinitionInterface $field_definition) { public static function schema(FieldDefinitionInterface $field_definition) {
return parent::schema($field_definition) + array( return array(
'columns' => array( 'columns' => array(
'value' => array( 'value' => array(
'type' => 'varchar', 'type' => 'varchar',
...@@ -40,19 +51,31 @@ public static function schema(FieldDefinitionInterface $field_definition) { ...@@ -40,19 +51,31 @@ public static function schema(FieldDefinitionInterface $field_definition) {
'not null' => FALSE, 'not null' => FALSE,
), ),
), ),
'indexes' => array(
'value' => array('value'),
),
); );
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public static function propertyDefinitions(FieldDefinitionInterface $field_definition) { protected function allowedValuesDescription() {
$constraints = array('Length' => array('max' => 255)); $description = '<p>' . t('The possible values this field can contain. Enter one value per line, in the format key|label.');
$properties['value'] = DataDefinition::create('string') $description .= '<br/>' . t('The key is the stored value. The label will be used in displayed values and edit forms.');
->setLabel(t('Text value')) $description .= '<br/>' . t('The label is optional: if a line contains a single string, it will be used as key and label.');
->setConstraints($constraints); $description .= '</p>';
$description .= '<p>' . t('Allowed HTML tags in labels: @tags', array('@tags' => _field_filter_xss_display_allowed_tags())) . '</p>';
return $description;
}
return $properties; /**
* {@inheritdoc}
*/
protected static function validateAllowedValue($option) {
if (drupal_strlen($option) > 255) {
return t('Allowed values list: each key must be a string at most 255 characters long.');
}
} }
} }
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
* Defines selection, check box and radio button widgets for text and numeric fields. * Defines selection, check box and radio button widgets for text and numeric fields.
*/ */
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\field\FieldConfigInterface; use Drupal\field\FieldConfigInterface;
...@@ -33,15 +32,6 @@ function options_help($path, $arg) { ...@@ -33,15 +32,6 @@ function options_help($path, $arg) {
} }
} }
/**
* Form element #value_callback: assembles the allowed values for 'boolean' fields.
*/
function options_field_settings_form_value_boolean_allowed_values($element, $input, $form_state) {
$on = NestedArray::getValue($form_state['input'], $element['#on_parents']);
$off = NestedArray::getValue($form_state['input'], $element['#off_parents']);
return array($off, $on);
}
/** /**
* Implements hook_ENTITY_TYPE_update() for 'field_config'. * Implements hook_ENTITY_TYPE_update() for 'field_config'.
*/ */
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment