datafield-1.x-dev/src/Plugin/DataField/FieldType/IntegerItem.php
src/Plugin/DataField/FieldType/IntegerItem.php
<?php
namespace Drupal\datafield\Plugin\DataField\FieldType;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\TypedData\DataDefinition;
use Drupal\datafield\Attribute\DataFieldType;
use Drupal\datafield\Plugin\DataFieldTypeInterface;
/**
* Defines the 'integer' field type.
*/
#[DataFieldType(
id: 'integer',
label: new TranslatableMarkup('Number (integer)'),
description: new TranslatableMarkup('This field stores a number in the database in a integer.'),
category: 'number',
default_widget: 'number',
default_formatter: 'number_integer',
)]
class IntegerItem implements DataFieldTypeInterface {
use StringTranslationTrait;
/**
* {@inheritdoc}
*/
public static function defaultStorageSettings() {
return [
'unsigned' => FALSE,
// Valid size property values include: 'tiny', 'small', 'medium', 'normal'
// and 'big'.
'size' => 'normal',
'type' => 'int',
'not null' => FALSE,
];
}
/**
* {@inheritdoc}
*/
public static function defaultFieldSettings() {
return [
'min' => '',
'max' => '',
'prefix' => '',
'suffix' => '',
];
}
/**
* {@inheritdoc}
*/
public static function schema(array $settings) {
$default = self::defaultStorageSettings();
if (!empty($settings['unsigned'])) {
$default['unsigned'] = $settings['unsigned'];
}
if (!empty($settings['size'])) {
$default['size'] = $settings['size'];
}
return [
'columns' => [
'value' => $default,
],
];
}
/**
* {@inheritdoc}
*/
public static function generateSampleValue($settings = []) {
$min = $settings['min'] ?? 0;
$max = $settings['max'] ?? 999;
return mt_rand($min, $max);
}
/**
* {@inheritdoc}
*/
public function getPluginId() {
return '';
}
/**
* {@inheritdoc}
*/
public function getPluginDefinition() {
return [];
}
/**
* {@inheritdoc}
*/
public static function propertyDefinitions(array $settings) {
$name = $settings['name'];
$data_type = 'integer';
return DataDefinition::create($data_type)
->setLabel(new TranslatableMarkup('%name value', ['%name' => $name]))
->setRequired(FALSE);
}
/**
* {@inheritdoc}
*/
public function getLabel() {
return $this->t('Number');
}
/**
* {@inheritdoc}
*/
public function fieldSettingsForm(array $field_settings, array $settings) {
$description = [$this->t('The possible values this field can contain. Enter one value per line, in the format key|label.')];
$description[] = $this->t('The label will be used in displayed values and edit forms.');
$description[] = $this->t('The label is optional: if a line contains a single item, it will be used as key and label.');
$subfield = $field_settings['machine_name'];
$allowed_values = $field_settings['allowed_values'];
if (!empty($allowed_values) && is_array($allowed_values)) {
$allowed_values = $this->allowedValuesString($allowed_values);
}
$field_form = [
'label' => [
'#type' => 'textfield',
'#title' => $this->t('Label'),
'#default_value' => $field_settings['label'] ?? ucfirst($settings["name"]),
],
'required' => [
'#type' => 'checkbox',
'#title' => $this->t('Required'),
'#default_value' => $field_settings['required'] ?? FALSE,
],
'list' => [
'#type' => 'checkbox',
'#title' => $this->t('Limit allowed values'),
'#default_value' => $field_settings['list'] ?? FALSE,
],
'allowed_values' => [
'#type' => 'textarea',
'#title' => $this->t('Allowed values list'),
'#description' => implode('<br/>', $description),
'#default_value' => $allowed_values,
'#rows' => 10,
'#element_validate' => [[get_class($this), 'validateAllowedValues']],
'#storage_type' => $settings['type'],
'#storage_max_length' => $settings['max_length'],
'#field_name' => $field_settings['field_name'],
'#entity_type' => $field_settings['entity_type'],
'#allowed_values' => $field_settings['allowed_values'] ?? '',
'#states' => [
'invisible' => [":input[name='settings[field_settings][$subfield][list]']" => ['checked' => FALSE]],
],
],
'min' => [
'#type' => 'number',
'#title' => $this->t('Minimum'),
'#description' => $this->t('The minimum value that should be allowed in this field. Leave blank for no minimum.'),
'#default_value' => $field_settings['min'] ?? NULL,
],
'max' => [
'#type' => 'number',
'#title' => $this->t('Maximum'),
'#description' => $this->t('The maximum value that should be allowed in this field. Leave blank for no maximum.'),
'#default_value' => $field_settings['max'] ?? NULL,
],
'prefix' => [
'#type' => 'textfield',
'#title' => $this->t('Prefix'),
'#default_value' => $field_settings['prefix'] ?? NULL,
'#description' => $this->t("Define a string that should be prefixed to the value, like '$ ' or '€ '. Leave blank for none. Separate singular and plural values with a pipe ('pound|pounds')."),
],
'suffix' => [
'#type' => 'textfield',
'#title' => $this->t('Suffix'),
'#default_value' => $settings['suffix'] ?? NULL,
'#description' => $this->t("Define a string that should be suffixed to the value, like ' m', ' kb/s'. Leave blank for none. Separate singular and plural values with a pipe ('pound|pounds')."),
],
];
return $field_form;
}
/**
* Get constraints.
*
* {@inheritdoc}
*/
public function getConstraints(array $settings) {
$constraints = [];
if (is_numeric($settings['min'])) {
$constraints['Range']['min'] = $settings['min'];
}
if (is_numeric($settings['max'])) {
$constraints['Range']['max'] = $settings['max'];
}
if ($settings['required']) {
$constraints['NotBlank'] = [];
}
return $constraints;
}
/**
* Validate allowed values.
*
* {@inheritdoc}
*/
public static function validateAllowedValues(array $element, FormStateInterface $form_state) {
$values = static::extractAllowedValues($element['#value']);
// Check if keys are valid for the field type.
foreach ($values as $key => $value) {
if (!is_numeric($key)) {
$form_state->setError($element, ('Allowed values list: keys must be integers.'));
}
}
}
/**
* Extracts the allowed values array from the allowed_values element.
*
* @param string $string
* The raw string to extract values from.
*
* @return array
* The array of extracted key/value pairs.
*
* @see \Drupal\options\Plugin\Field\FieldType\ListTextItem::extractAllowedValues()
*/
protected static function extractAllowedValues(string $string): array {
$values = [];
$list = explode("\n", $string);
$list = array_map('trim', $list);
$list = array_filter($list, 'strlen');
foreach ($list as $text) {
// Check for an explicit key.
if (preg_match('/(.*)\|(.*)/', $text, $matches)) {
// Trim key and value to avoid unwanted spaces issues.
$key = trim($matches[1]);
$value = trim($matches[2]);
}
else {
$key = $value = $text;
}
$values[$key] = $value;
}
return $values;
}
/**
* 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(array $values): string {
$lines = [];
foreach ($values as $key => $value) {
$lines[] = "$key|$value";
}
return implode("\n", $lines);
}
}
