datafield-1.x-dev/src/Plugin/DataField/FieldType/StringItem.php
src/Plugin/DataField/FieldType/StringItem.php
<?php
namespace Drupal\datafield\Plugin\DataField\FieldType;
use Drupal\Component\Utility\Random;
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 'string' entity field type.
*/
#[DataFieldType(
id: 'string',
label: new TranslatableMarkup('Text (plain)'),
description: new TranslatableMarkup('A field containing a plain string value.'),
default_widget: 'textfield',
default_formatter: 'string',
no_ui: TRUE,
)]
class StringItem implements DataFieldTypeInterface {
use StringTranslationTrait;
const MAX_LENGTH = 255;
/**
* {@inheritdoc}
*/
protected array $settings;
/**
* {@inheritdoc}
*/
public function __construct(array $settings = []) {
$this->settings = $settings;
}
/**
* {@inheritdoc}
*/
public function getSetting(string $name) {
return $this->settings[$name];
}
/**
* {@inheritdoc}
*/
public static function defaultStorageSettings() {
return [
'type' => 'varchar',
'length' => self::MAX_LENGTH,
'is_ascii' => FALSE,
'not null' => FALSE,
];
}
/**
* {@inheritdoc}
*/
public static function schema(array $settings) {
$default = self::defaultStorageSettings();
if (!empty($settings['max_length'])) {
$default['length'] = $settings['max_length'];
}
return [
'columns' => [
'value' => $default,
],
];
}
/**
* {@inheritdoc}
*/
public static function generateSampleValue() {
$random = new Random();
return $random->word(mt_rand(1, self::MAX_LENGTH));
}
/**
* {@inheritdoc}
*/
public function getPluginId() {
return '';
}
/**
* {@inheritdoc}
*/
public function getPluginDefinition() {
return [];
}
/**
* {@inheritdoc}
*/
public static function propertyDefinitions(array $settings) {
$name = $settings['name'];
$data_type = 'string';
return DataDefinition::create($data_type)
->setLabel(new TranslatableMarkup('%name value', ['%name' => $name]))
->setRequired(FALSE);
}
/**
* {@inheritdoc}
*/
public function getLabel() {
return $this->t('String');
}
/**
* {@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'];
$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' => !empty($field_settings['allowed_values']) ? $this->allowedValuesString($field_settings['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]],
],
],
];
return $field_form;
}
/**
* Get constraints.
*
* {@inheritdoc}
*/
public function getConstraints(array $settings) {
$constraints = [];
if (!empty($settings["list"]) && !empty($settings['allowed_values'])) {
if (is_string($settings['allowed_values'])) {
$settings['allowed_values'] = static::extractAllowedValues($settings['allowed_values']);
}
// $constraints['AllowedValues'] =array_keys($settings['allowed_values']);
}
if (!empty($settings['max_length'])) {
$constraints['Length']['max'] = $settings['max_length'];
}
if (!empty($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 (mb_strlen($key) > $element['#storage_max_length']) {
$error_message = t(
'Allowed values list: each key must be a string at most @maxlength characters long.',
['@maxlength' => $element['#storage_max_length']]
);
$form_state->setError($element, $error_message);
}
}
}
/**
* 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|mixed $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(mixed $values): string {
$lines = [];
if (is_string($values)) {
return $values;
}
foreach ($values as $key => $value) {
$lines[] = "$key|$value";
}
return implode(PHP_EOL, $lines);
}
}
