You are here

class DoubleField in Double Field 4.x

Same name in this branch
  1. 4.x src/Feeds/Target/DoubleField.php \Drupal\double_field\Feeds\Target\DoubleField
  2. 4.x src/Plugin/Field/FieldType/DoubleField.php \Drupal\double_field\Plugin\Field\FieldType\DoubleField
Same name and namespace in other branches
  1. 8.3 src/Plugin/Field/FieldType/DoubleField.php \Drupal\double_field\Plugin\Field\FieldType\DoubleField

Plugin implementation of the 'double_field' field type.

Plugin annotation


@FieldType(
  id = "double_field",
  label = @Translation("Double Field"),
  description = @Translation("Double Field."),
  default_widget = "double_field",
  default_formatter = "double_field_unformatted_list"
)

Hierarchy

Expanded class hierarchy of DoubleField

2 files declare their use of DoubleField
Base.php in src/Plugin/Field/FieldFormatter/Base.php
TestBase.php in tests/src/FunctionalJavascript/TestBase.php

File

src/Plugin/Field/FieldType/DoubleField.php, line 26

Namespace

Drupal\double_field\Plugin\Field\FieldType
View source
class DoubleField extends FieldItemBase {
  public const DATETIME_STORAGE_TIMEZONE = 'UTC';
  public const DATETIME_DATETIME_STORAGE_FORMAT = 'Y-m-d\\TH:i:s';
  public const DATETIME_DATE_STORAGE_FORMAT = 'Y-m-d';

  /**
   * {@inheritdoc}
   */
  public static function defaultStorageSettings() : array {
    $settings = [];
    foreach ([
      'first',
      'second',
    ] as $subfield) {
      $settings['storage'][$subfield] = [
        'type' => 'string',
        'maxlength' => 255,
        'precision' => 10,
        'scale' => 2,
        'datetime_type' => 'datetime',
      ];
    }
    return $settings + parent::defaultStorageSettings();
  }

  /**
   * {@inheritdoc}
   */
  public function storageSettingsForm(array &$form, FormStateInterface $form_state, $has_data) : array {
    $settings = $this
      ->getSettings();
    $element = [];
    foreach ([
      'first',
      'second',
    ] as $subfield) {
      $element['storage'][$subfield] = [
        '#type' => 'details',
        '#title' => $subfield == 'first' ? $this
          ->t('First subfield') : $this
          ->t('Second subfield'),
        '#open' => TRUE,
      ];
      $element['storage'][$subfield]['type'] = [
        '#type' => 'select',
        '#title' => $this
          ->t('Field type'),
        '#default_value' => $settings['storage'][$subfield]['type'],
        '#disabled' => $has_data,
        '#required' => TRUE,
        '#options' => $this
          ->subfieldTypes(),
      ];
      $element['storage'][$subfield]['maxlength'] = [
        '#type' => 'number',
        '#title' => $this
          ->t('Maximum length'),
        '#description' => $this
          ->t('The maximum length of the subfield in characters.'),
        '#default_value' => $settings['storage'][$subfield]['maxlength'],
        '#disabled' => $has_data,
        '#required' => TRUE,
        '#min' => 1,
        '#states' => [
          'visible' => [
            ":input[name='settings[storage][{$subfield}][type]']" => [
              'value' => 'string',
            ],
          ],
        ],
      ];
      $element['storage'][$subfield]['precision'] = [
        '#type' => 'number',
        '#title' => $this
          ->t('Precision'),
        '#description' => $this
          ->t('The total number of digits to store in the database, including those to the right of the decimal.'),
        '#default_value' => $settings['storage'][$subfield]['precision'],
        '#disabled' => $has_data,
        '#required' => TRUE,
        '#min' => 10,
        '#max' => 32,
        '#states' => [
          'visible' => [
            ":input[name='settings[storage][{$subfield}][type]']" => [
              'value' => 'numeric',
            ],
          ],
        ],
      ];
      $element['storage'][$subfield]['scale'] = [
        '#type' => 'number',
        '#title' => $this
          ->t('Scale'),
        '#description' => $this
          ->t('The number of digits to the right of the decimal.'),
        '#default_value' => $settings['storage'][$subfield]['scale'],
        '#disabled' => $has_data,
        '#required' => TRUE,
        '#min' => 0,
        '#max' => 10,
        '#states' => [
          'visible' => [
            ":input[name='settings[storage][{$subfield}][type]']" => [
              'value' => 'numeric',
            ],
          ],
        ],
      ];
      $element['storage'][$subfield]['datetime_type'] = [
        '#type' => 'radios',
        '#title' => $this
          ->t('Date type'),
        '#description' => $this
          ->t('Choose the type of date to create.'),
        '#default_value' => $settings['storage'][$subfield]['datetime_type'],
        '#disabled' => $has_data,
        '#options' => [
          'datetime' => $this
            ->t('Date and time'),
          'date' => $this
            ->t('Date only'),
        ],
        '#states' => [
          'visible' => [
            ":input[name='settings[storage][{$subfield}][type]']" => [
              'value' => 'datetime_iso8601',
            ],
          ],
        ],
      ];
    }
    return $element;
  }

  /**
   * {@inheritdoc}
   */
  public static function defaultFieldSettings() : array {
    $settings = [];
    foreach ([
      'first',
      'second',
    ] as $subfield) {
      $settings[$subfield] = [
        'label' => '',
        'min' => '',
        'max' => '',
        'list' => FALSE,
        'allowed_values' => [],
        'required' => TRUE,
        'on_label' => t('On'),
        'off_label' => t('Off'),
      ];
    }
    return $settings + parent::defaultFieldSettings();
  }

  /**
   * {@inheritdoc}
   */
  public function fieldSettingsForm(array $form, FormStateInterface $form_state) : array {
    $settings = $this
      ->getSettings();
    $types = static::subfieldTypes();
    $element = [];
    foreach ([
      'first',
      'second',
    ] as $subfield) {
      $type = $settings['storage'][$subfield]['type'];
      $title = $subfield == 'first' ? $this
        ->t('First subfield') : $this
        ->t('Second subfield');
      $title .= ' - ' . $types[$type];
      $element[$subfield] = [
        '#type' => 'details',
        '#title' => $title,
        '#open' => FALSE,
        '#tree' => TRUE,
      ];
      $element[$subfield]['label'] = [
        '#type' => 'textfield',
        '#title' => $this
          ->t('Label'),
        '#default_value' => $settings[$subfield]['label'],
      ];
      $element[$subfield]['required'] = [
        '#type' => 'checkbox',
        '#title' => $this
          ->t('Required'),
        '#default_value' => $settings[$subfield]['required'],
      ];
      if (static::isListAllowed($type)) {
        $element[$subfield]['list'] = [
          '#type' => 'checkbox',
          '#title' => $this
            ->t('Limit allowed values'),
          '#default_value' => $settings[$subfield]['list'],
        ];
        $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.');
        $element[$subfield]['allowed_values'] = [
          '#type' => 'textarea',
          '#title' => $this
            ->t('Allowed values list'),
          '#description' => implode('<br/>', $description),
          '#default_value' => $this
            ->allowedValuesString($settings[$subfield]['allowed_values']),
          '#rows' => 10,
          '#element_validate' => [
            [
              get_class($this),
              'validateAllowedValues',
            ],
          ],
          // @see: DoubleField::validateAllowedValues()
          '#storage_type' => $type,
          '#storage_maxlength' => $settings['storage'][$subfield]['maxlength'],
          '#field_name' => $this
            ->getFieldDefinition()
            ->getName(),
          '#entity_type' => $this
            ->getEntity()
            ->getEntityTypeId(),
          '#allowed_values' => $settings[$subfield]['allowed_values'],
          '#states' => [
            'invisible' => [
              ":input[name='settings[{$subfield}][list]']" => [
                'checked' => FALSE,
              ],
            ],
          ],
        ];
      }
      else {
        $element[$subfield]['list'] = [
          '#type' => 'value',
          '#default_value' => FALSE,
        ];
        $element[$subfield]['allowed_values'] = [
          '#type' => 'value',
          '#default_value' => [],
        ];
      }
      if (in_array($type, [
        'integer',
        'float',
        'numeric',
      ])) {
        $element[$subfield]['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' => $settings[$subfield]['min'] ?? NULL,
          '#states' => [
            'visible' => [
              ":input[name='settings[{$subfield}][list]']" => [
                'checked' => FALSE,
              ],
            ],
          ],
        ];
        $element[$subfield]['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' => $settings[$subfield]['max'] ?? NULL,
          '#states' => [
            'visible' => [
              ":input[name='settings[{$subfield}][list]']" => [
                'checked' => FALSE,
              ],
            ],
          ],
        ];
      }
      else {
        $element[$subfield]['min'] = $element[$subfield]['max'] = [
          '#type' => 'value',
          '#default_value' => '',
        ];
      }
      if ($type == 'boolean') {
        $element[$subfield]['on_label'] = [
          '#type' => 'textfield',
          '#title' => $this
            ->t('"On" label'),
          '#default_value' => $settings[$subfield]['on_label'],
        ];
        $element[$subfield]['off_label'] = [
          '#type' => 'textfield',
          '#title' => $this
            ->t('"Off" label'),
          '#default_value' => $settings[$subfield]['off_label'],
        ];
      }
      else {
        $element[$subfield]['on_label'] = [
          '#type' => 'value',
          '#default_value' => $settings[$subfield]['on_label'],
        ];
        $element[$subfield]['off_label'] = [
          '#type' => 'value',
          '#default_value' => $settings[$subfield]['off_label'],
        ];
      }
    }
    return $element;
  }

  /**
   * {@inheritdoc}
   *
   * @todo Find a way to disable constraints for default field values.
   */
  public function getConstraints() : array {
    $constraint_manager = \Drupal::typedDataManager()
      ->getValidationConstraintManager();
    $constraints = parent::getConstraints();
    $settings = $this
      ->getSettings();
    $subconstrains = [];
    foreach ([
      'first',
      'second',
    ] as $subfield) {
      $subfield_type = $settings['storage'][$subfield]['type'];
      $is_list = $settings[$subfield]['list'] && static::isListAllowed($subfield_type);
      if ($is_list && $settings[$subfield]['allowed_values']) {
        $allowed_values = array_keys($settings[$subfield]['allowed_values']);
        $subconstrains[$subfield]['AllowedValues'] = $allowed_values;
      }
      if ($subfield_type == 'string' || $subfield_type == 'telephone') {
        $subconstrains[$subfield]['Length']['max'] = $settings['storage'][$subfield]['maxlength'];
      }

      // Allowed values take precedence over the range constraints.
      $numeric_types = [
        'integer',
        'float',
        'numeric',
      ];
      if (!$settings[$subfield]['list'] && in_array($subfield_type, $numeric_types)) {
        if (is_numeric($settings[$subfield]['min'])) {
          $subconstrains[$subfield]['Range']['min'] = $settings[$subfield]['min'];
        }
        if (is_numeric($settings[$subfield]['max'])) {
          $subconstrains[$subfield]['Range']['max'] = $settings[$subfield]['max'];
        }
      }
      if ($subfield_type == 'email') {
        $subconstrains[$subfield]['Length']['max'] = Email::EMAIL_MAX_LENGTH;
      }
      if ($settings[$subfield]['required']) {

        // NotBlank validator is not suitable for booleans because it does not
        // recognize '0' as an empty value.
        if ($subfield_type == 'boolean') {
          $subconstrains[$subfield]['NotEqualTo']['value'] = 0;
          $subconstrains[$subfield]['NotEqualTo']['message'] = $this
            ->t('This value should not be blank.');
        }
        else {
          $subconstrains[$subfield]['NotBlank'] = [];
        }
      }
    }
    $constraints[] = $constraint_manager
      ->create('ComplexData', $subconstrains);
    return $constraints;
  }

  /**
   * {@inheritdoc}
   */
  public static function schema(FieldStorageDefinitionInterface $field_definition) : array {
    $settings = $field_definition
      ->getSettings();
    $columns = [];
    foreach ([
      'first',
      'second',
    ] as $subfield) {
      $type = $settings['storage'][$subfield]['type'];
      $columns[$subfield] = [
        'not null' => FALSE,
        'description' => ucfirst($subfield) . ' subfield value.',
      ];
      switch ($type) {
        case 'string':
        case 'telephone':
          $columns[$subfield]['type'] = 'varchar';
          $columns[$subfield]['length'] = $settings['storage'][$subfield]['maxlength'];
          break;
        case 'text':
          $columns[$subfield]['type'] = 'text';
          $columns[$subfield]['size'] = 'big';
          break;
        case 'integer':
          $columns[$subfield]['type'] = 'int';
          $columns[$subfield]['size'] = 'normal';
          break;
        case 'float':
          $columns[$subfield]['type'] = 'float';

          // Big makes the float behaviour less surprising.
          $columns[$subfield]['size'] = 'big';
          break;
        case 'boolean':
          $columns[$subfield]['type'] = 'int';
          $columns[$subfield]['size'] = 'tiny';
          break;
        case 'numeric':
          $columns[$subfield]['type'] = 'numeric';
          $columns[$subfield]['precision'] = $settings['storage'][$subfield]['precision'];
          $columns[$subfield]['scale'] = $settings['storage'][$subfield]['scale'];
          break;
        case 'email':
          $columns[$subfield]['type'] = 'varchar';
          $columns[$subfield]['length'] = Email::EMAIL_MAX_LENGTH;
          break;
        case 'uri':
          $columns[$subfield]['type'] = 'varchar';
          $columns[$subfield]['length'] = 2048;
          break;
        case 'datetime_iso8601':
          $columns[$subfield]['type'] = 'varchar';
          $columns[$subfield]['length'] = 20;
          break;
      }
    }
    return [
      'columns' => $columns,
    ];
  }

  /**
   * {@inheritdoc}
   */
  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
    $subfield_types = static::subfieldTypes();
    $settings = $field_definition
      ->getSettings();
    $properties = [];
    foreach ([
      'first',
      'second',
    ] as $subfield) {
      $subfield_type = $settings['storage'][$subfield]['type'];

      // Typed data are slightly different from schema the definition.
      if ($subfield_type == 'text' || $subfield_type == 'telephone') {
        $subfield_type = 'string';
      }
      elseif ($subfield_type == 'numeric') {
        $subfield_type = 'float';
      }
      $properties[$subfield] = DataDefinition::create($subfield_type)
        ->setLabel($subfield_types[$subfield_type]);
    }
    return $properties;
  }

  /**
   * {@inheritdoc}
   */
  public function isEmpty() : bool {
    $settings = $this
      ->getSettings();
    foreach ([
      'first',
      'second',
    ] as $subfield) {
      if ($settings['storage'][$subfield]['type'] == 'boolean') {

        // Booleans can be 1 or 0.
        if ($this->{$subfield} == 1) {
          return FALSE;
        }
      }
      elseif ($this->{$subfield} !== NULL && $this->{$subfield} !== '') {
        return FALSE;
      }
    }
    return TRUE;
  }

  /**
   * Element validate callback for subfield allowed values.
   *
   * @param array $element
   *   An associative array containing the properties and children of the
   *   generic form element.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form for the form this element belongs to.
   *
   * @see \Drupal\Core\Render\Element\FormElement::processPattern()
   */
  public static function validateAllowedValues(array $element, FormStateInterface $form_state) : void {
    $values = static::extractAllowedValues($element['#value']);

    // Check if keys are valid for the field type.
    foreach ($values as $key => $value) {
      switch ($element['#storage_type']) {
        case 'string':

          // @see \Drupal\options\Plugin\Field\FieldType\ListStringItem::validateAllowedValue()
          if (mb_strlen($key) > $element['#storage_maxlength']) {
            $error_message = t('Allowed values list: each key must be a string at most @maxlength characters long.', [
              '@maxlength' => $element['#storage_maxlength'],
            ]);
            $form_state
              ->setError($element, $error_message);
          }
          break;
        case 'integer':

          // @see \Drupal\options\Plugin\Field\FieldType\ListIntegerItem::validateAllowedValue()
          if (!preg_match('/^-?\\d+$/', $key)) {
            $form_state
              ->setError($element, 'Allowed values list: keys must be integers.');
          }
          break;
        case 'float':
        case 'numeric':

          // @see \Drupal\options\Plugin\Field\FieldType\ListFloatItem::validateAllowedValue()
          if (!is_numeric($key)) {
            $form_state
              ->setError($element, 'Allowed values list: each key must be a valid integer or decimal.');
          }
          break;
      }
    }
    $form_state
      ->setValueForElement($element, $values);
  }

  /**
   * 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);
  }

  /**
   * Returns available subfield storage types.
   */
  public static function subfieldTypes() : array {
    return [
      'boolean' => t('Boolean'),
      'string' => t('Text'),
      'text' => t('Text (long)'),
      'integer' => t('Integer'),
      'float' => t('Float'),
      'numeric' => t('Decimal'),
      'email' => t('Email'),
      'telephone' => t('Telephone'),
      'datetime_iso8601' => t('Date'),
      // We only allow external links. So this should be URL from the user side.
      'uri' => t('Url'),
    ];
  }

  /**
   * {@inheritdoc}
   */
  public static function fieldSettingsToConfigData(array $settings) : array {
    foreach ([
      'first',
      'second',
    ] as $subfield) {
      $structured_values = [];
      foreach ($settings[$subfield]['allowed_values'] as $value => $label) {
        $structured_values[] = [
          'value' => $value,
          'label' => $label,
        ];
      }
      $settings[$subfield]['allowed_values'] = $structured_values;
    }
    return $settings;
  }

  /**
   * {@inheritdoc}
   */
  public static function fieldSettingsFromConfigData(array $settings) : array {
    foreach ([
      'first',
      'second',
    ] as $subfield) {
      $structured_values = [];
      foreach ($settings[$subfield]['allowed_values'] as $item) {
        $structured_values[$item['value']] = $item['label'];
      }
      $settings[$subfield]['allowed_values'] = $structured_values;
    }
    return $settings;
  }

  /**
   * Checks if list option is allowed for a given sub-field type.
   */
  public static function isListAllowed(string $subfield_type) : bool {
    $list_types = [
      'string',
      'integer',
      'float',
      'numeric',
      'email',
      'telephone',
      'uri',
      'datetime_iso8601',
    ];
    return in_array($subfield_type, $list_types);
  }

  /**
   * {@inheritdoc}
   */
  public static function generateSampleValue(FieldDefinitionInterface $field_definition) : array {
    $settings = $field_definition
      ->getSettings();
    $data = [];
    foreach ([
      'first',
      'second',
    ] as $subfield) {

      // If allowed values are limited pick one of them from field settings.
      if ($settings[$subfield]['list']) {
        $data[$subfield] = array_rand($settings[$subfield]['allowed_values']);
        continue;
      }
      switch ($settings['storage'][$subfield]['type']) {

        // @see \Drupal\Core\Field\Plugin\Field\FieldType\BooleanItem::generateSampleValue()
        case 'boolean':
          $data[$subfield] = (bool) mt_rand(0, 1);
          break;

        // @see \Drupal\datetime\Plugin\Field\FieldType\DateTimeItem::generateSampleValue()
        case 'datetime_iso8601':
          $date_type = $settings['storage'][$subfield]['datetime_type'];
          $timestamp = \Drupal::time()
            ->getRequestTime() - mt_rand(0, 86400 * 365);
          $storage_format = $date_type == 'date' ? self::DATETIME_DATE_STORAGE_FORMAT : self::DATETIME_DATETIME_STORAGE_FORMAT;
          $data[$subfield] = gmdate($storage_format, $timestamp);
          break;

        // @see \Drupal\Core\Field\Plugin\Field\FieldType\StringItem::generateSampleValue()
        case 'string':
          $data[$subfield] = (new Random())
            ->word(mt_rand(1, $settings['storage'][$subfield]['maxlength']));
          break;

        // @see \Drupal\text\Plugin\Field\FieldType\TextItemBase::generateSampleValue()
        case 'text':
          $data[$subfield] = (new Random())
            ->paragraphs(5);
          break;

        // @see \Drupal\Core\Field\Plugin\Field\FieldType\IntegerItem::generateSampleValue()
        case 'integer':
          $min = is_numeric($settings[$subfield]['min']) ? $settings[$subfield]['min'] : -1000;
          $max = is_numeric($settings[$subfield]['max']) ? $settings[$subfield]['max'] : 1000;
          $data[$subfield] = mt_rand($min, $max);
          break;

        // @see \Drupal\Core\Field\Plugin\Field\FieldType\FloatItem::generateSampleValue()
        case 'float':
          $settings = $field_definition
            ->getSettings();
          $precision = rand(10, 32);
          $scale = rand(1, 5);
          $max = is_numeric($settings[$subfield]['min']) ? $settings[$subfield]['min'] : pow(10, $precision - $scale) - 1;
          $min = is_numeric($settings[$subfield]['max']) ? $settings[$subfield]['max'] : -pow(10, $precision - $scale) + 1;
          $random_decimal = $min + mt_rand() / mt_getrandmax() * ($max - $min);
          $data[$subfield] = floor($random_decimal * pow(10, $scale)) / pow(10, $scale);
          break;

        // @see \Drupal\Core\Field\Plugin\Field\FieldType\DecimalItem::generateSampleValue()
        case 'numeric':
          $precision = $settings['storage'][$subfield]['precision'] ?: 10;
          $scale = $settings['storage'][$subfield]['scale'] ?: 2;
          $min = is_numeric($settings[$subfield]['min']) ? $settings[$subfield]['min'] : -pow(10, $precision - $scale) + 1;
          $max = is_numeric($settings[$subfield]['max']) ? $settings[$subfield]['max'] : pow(10, $precision - $scale) - 1;
          $set_decimal_digits = function ($decimal) {
            $digits = 0;
            while ($decimal - round($decimal)) {
              $decimal *= 10;
              $digits++;
            }
            return $digits;
          };
          $decimal_digits = $set_decimal_digits($max);
          $decimal_digits = max($set_decimal_digits($min), $decimal_digits);
          $scale = rand($decimal_digits, $scale);
          $random_decimal = $min + mt_rand() / mt_getrandmax() * ($max - $min);
          $data[$subfield] = floor($random_decimal * pow(10, $scale)) / pow(10, $scale);
          break;

        // @see \Drupal\Core\Field\Plugin\Field\FieldType\EmailItem::generateSampleValue()
        case 'email':
          $data[$subfield] = strtolower((new Random())
            ->name()) . '@example.com';
          break;

        // @see \Drupal\telephone\Plugin\Field\FieldType\TelephoneItem::generateSampleValue()
        case 'telephone':
          $data[$subfield] = mt_rand(pow(10, 8), pow(10, 9) - 1);
          break;

        // @see \Drupal\link\Plugin\Field\FieldType\LinkItem::generateSampleValue()
        case 'uri':
          $random = new Random();
          $tlds = [
            'com',
            'net',
            'gov',
            'org',
            'edu',
            'biz',
            'info',
          ];
          $domain_length = mt_rand(7, 15);
          $protocol = mt_rand(0, 1) ? 'https' : 'http';
          $www = mt_rand(0, 1) ? 'www' : '';
          $domain = $random
            ->word($domain_length);
          $tld = $tlds[mt_rand(0, count($tlds) - 1)];
          $data[$subfield] = "{$protocol}://{$www}.{$domain}.{$tld}";
          break;
      }
    }
    return $data;
  }

  /**
   * Creates date object for a given subfield using storage timezone.
   */
  public function createDate(string $subfield) : ?DateTimePlus {
    $date = NULL;
    if ($this->{$subfield}) {
      $is_date_only = $this
        ->getSetting('storage')[$subfield]['datetime_type'] == 'date';
      $format = $is_date_only ? static::DATETIME_DATE_STORAGE_FORMAT : static::DATETIME_DATETIME_STORAGE_FORMAT;
      $date = DrupalDateTime::createFromFormat($format, $this->{$subfield}, static::DATETIME_STORAGE_TIMEZONE);
      if ($is_date_only) {
        $date
          ->setDefaultDateTime();
      }
    }
    return $date;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
DependencySerializationTrait::$_entityStorages protected property
DependencySerializationTrait::$_serviceIds protected property
DependencySerializationTrait::__sleep public function 2
DependencySerializationTrait::__wakeup public function 2
DoubleField::allowedValuesString protected function Generates a string representation of an array of 'allowed values'.
DoubleField::createDate public function Creates date object for a given subfield using storage timezone.
DoubleField::DATETIME_DATETIME_STORAGE_FORMAT public constant
DoubleField::DATETIME_DATE_STORAGE_FORMAT public constant
DoubleField::DATETIME_STORAGE_TIMEZONE public constant
DoubleField::defaultFieldSettings public static function Defines the field-level settings for this plugin. Overrides FieldItemBase::defaultFieldSettings
DoubleField::defaultStorageSettings public static function Defines the storage-level settings for this plugin. Overrides FieldItemBase::defaultStorageSettings
DoubleField::extractAllowedValues protected static function Extracts the allowed values array from the allowed_values element.
DoubleField::fieldSettingsForm public function Returns a form for the field-level settings. Overrides FieldItemBase::fieldSettingsForm
DoubleField::fieldSettingsFromConfigData public static function Returns a settings array in the field type's canonical representation. Overrides FieldItemBase::fieldSettingsFromConfigData
DoubleField::fieldSettingsToConfigData public static function Returns a settings array that can be stored as a configuration value. Overrides FieldItemBase::fieldSettingsToConfigData
DoubleField::generateSampleValue public static function Generates placeholder field values. Overrides FieldItemBase::generateSampleValue
DoubleField::getConstraints public function @todo Find a way to disable constraints for default field values. Overrides TypedData::getConstraints
DoubleField::isEmpty public function Determines whether the data structure is empty. Overrides Map::isEmpty
DoubleField::isListAllowed public static function Checks if list option is allowed for a given sub-field type.
DoubleField::propertyDefinitions public static function Defines field item properties. Overrides FieldItemInterface::propertyDefinitions
DoubleField::schema public static function Returns the schema for the field. Overrides FieldItemInterface::schema
DoubleField::storageSettingsForm public function Returns a form for the storage-level settings. Overrides FieldItemBase::storageSettingsForm
DoubleField::subfieldTypes public static function Returns available subfield storage types.
DoubleField::validateAllowedValues public static function Element validate callback for subfield allowed values.
FieldItemBase::calculateDependencies public static function Calculates dependencies for field items. Overrides FieldItemInterface::calculateDependencies 2
FieldItemBase::calculateStorageDependencies public static function Calculates dependencies for field items on the storage level. Overrides FieldItemInterface::calculateStorageDependencies 1
FieldItemBase::delete public function Defines custom delete behavior for field values. Overrides FieldItemInterface::delete 2
FieldItemBase::deleteRevision public function Defines custom revision delete behavior for field values. Overrides FieldItemInterface::deleteRevision
FieldItemBase::getEntity public function Gets the entity that field belongs to. Overrides FieldItemInterface::getEntity
FieldItemBase::getFieldDefinition public function Gets the field definition. Overrides FieldItemInterface::getFieldDefinition
FieldItemBase::getLangcode public function Gets the langcode of the field values held in the object. Overrides FieldItemInterface::getLangcode
FieldItemBase::getSetting protected function Returns the value of a field setting.
FieldItemBase::getSettings protected function Returns the array of field settings.
FieldItemBase::mainPropertyName public static function Returns the name of the main property, if any. Overrides FieldItemInterface::mainPropertyName 8
FieldItemBase::onDependencyRemoval public static function Informs the plugin that a dependency of the field will be deleted. Overrides FieldItemInterface::onDependencyRemoval 1
FieldItemBase::postSave public function Defines custom post-save behavior for field values. Overrides FieldItemInterface::postSave 2
FieldItemBase::preSave public function Defines custom presave behavior for field values. Overrides FieldItemInterface::preSave 7
FieldItemBase::setValue public function Sets the data value. Overrides Map::setValue 4
FieldItemBase::storageSettingsFromConfigData public static function Returns a settings array in the field type's canonical representation. Overrides FieldItemInterface::storageSettingsFromConfigData 2
FieldItemBase::storageSettingsToConfigData public static function Returns a settings array that can be stored as a configuration value. Overrides FieldItemInterface::storageSettingsToConfigData 2
FieldItemBase::view public function Returns a renderable array for a single field item. Overrides FieldItemInterface::view
FieldItemBase::writePropertyValue protected function Different to the parent Map class, we avoid creating property objects as far as possible in order to optimize performance. Thus we just update $this->values if no property object has been created yet. Overrides Map::writePropertyValue
FieldItemBase::__construct public function Constructs a TypedData object given its definition and context. Overrides TypedData::__construct 1
FieldItemBase::__get public function Magic method: Gets a property value. Overrides FieldItemInterface::__get 2
FieldItemBase::__isset public function Magic method: Determines whether a property is set. Overrides FieldItemInterface::__isset
FieldItemBase::__set public function Magic method: Sets a property value. Overrides FieldItemInterface::__set 1
FieldItemBase::__unset public function Magic method: Unsets a property. Overrides FieldItemInterface::__unset
Map::$definition protected property The data definition. Overrides TypedData::$definition
Map::$properties protected property The array of properties.
Map::$values protected property An array of values for the contained properties.
Map::applyDefaultValue public function Applies the default value. Overrides TypedData::applyDefaultValue 4
Map::get public function Gets a property object. Overrides ComplexDataInterface::get
Map::getIterator public function
Map::getProperties public function Gets an array of property objects. Overrides ComplexDataInterface::getProperties
Map::getString public function Returns a string representation of the data. Overrides TypedData::getString
Map::getValue public function Gets the data value. Overrides TypedData::getValue 1
Map::onChange public function Overrides TraversableTypedDataInterface::onChange 4
Map::set public function Sets a property value. Overrides ComplexDataInterface::set
Map::toArray public function Returns an array of all property values. Overrides ComplexDataInterface::toArray 1
Map::__clone public function Magic method: Implements a deep clone.
StringTranslationTrait::$stringTranslation protected property The string translation service. 4
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.
TypedData::$name protected property The property name.
TypedData::$parent protected property The parent typed data object.
TypedData::createInstance public static function Constructs a TypedData object given its definition and context. Overrides TypedDataInterface::createInstance
TypedData::getDataDefinition public function Gets the data definition. Overrides TypedDataInterface::getDataDefinition
TypedData::getName public function Returns the name of a property or item. Overrides TypedDataInterface::getName
TypedData::getParent public function Returns the parent data structure; i.e. either complex data or a list. Overrides TypedDataInterface::getParent
TypedData::getPluginDefinition public function Gets the definition of the plugin implementation. Overrides PluginInspectionInterface::getPluginDefinition
TypedData::getPluginId public function Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface::getPluginId
TypedData::getPropertyPath public function Returns the property path of the data. Overrides TypedDataInterface::getPropertyPath
TypedData::getRoot public function Returns the root of the typed data tree. Overrides TypedDataInterface::getRoot
TypedData::setContext public function Sets the context of a property or item via a context aware parent. Overrides TypedDataInterface::setContext
TypedData::validate public function Validates the currently set data value. Overrides TypedDataInterface::validate
TypedDataTrait::$typedDataManager protected property The typed data manager used for creating the data types.
TypedDataTrait::getTypedDataManager public function Gets the typed data manager. 2
TypedDataTrait::setTypedDataManager public function Sets the typed data manager. 2