MeasurementItem.php 4.14 KB
Newer Older
bojanz's avatar
bojanz committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
<?php

namespace Drupal\physical\Plugin\Field\FieldType;

use Drupal\Core\Field\FieldItemBase;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Field\PreconfiguredFieldUiOptionsInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\TypedData\DataDefinition;
use Drupal\physical\Measurement;
use Drupal\physical\MeasurementType;

/**
 * Plugin implementation of the 'physical_measurement' field type.
 *
 * @FieldType(
 *   id = "physical_measurement",
 *   label = @Translation("Measurement"),
 *   description = @Translation("This field stores a number and a unit of measure."),
 *   category = @Translation("Physical"),
 *   default_widget = "physical_measurement_default",
 *   default_formatter = "physical_measurement_default"
 * )
 */
class MeasurementItem extends FieldItemBase implements PreconfiguredFieldUiOptionsInterface {

  /**
   * {@inheritdoc}
   */
  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
    $properties['number'] = DataDefinition::create('string')
      ->setLabel(t('Number'));
    $properties['unit'] = DataDefinition::create('string')
      ->setLabel(t('Unit'));

    return $properties;
  }

  /**
   * {@inheritdoc}
   */
  public static function schema(FieldStorageDefinitionInterface $field_definition) {
    return [
      'columns' => [
        'number' => [
          'description' => 'The number.',
          'type' => 'numeric',
          'precision' => 19,
          'scale' => 6,
        ],
        'unit' => [
          'description' => 'The unit.',
          'type' => 'varchar',
          'length' => '255',
          'default' => '',
        ],
      ],
    ];
  }

  /**
   * {@inheritdoc}
   */
  public static function mainPropertyName() {
    return NULL;
  }

  /**
   * {@inheritdoc}
   */
  public function getConstraints() {
72
    $constraint_manager = $this->getTypedDataManager()->getValidationConstraintManager();
bojanz's avatar
bojanz committed
73
    $constraints = parent::getConstraints();
74
    $constraints[] = $constraint_manager->create('ComplexData', [
bojanz's avatar
bojanz committed
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
      'number' => [
        'Regex' => [
          'pattern' => '/^[+-]?((\d+(\.\d*)?)|(\.\d+))$/i',
        ],
      ],
    ]);

    return $constraints;
  }

  /**
   * {@inheritdoc}
   */
  public function isEmpty() {
    return $this->number === NULL || $this->number === '' || empty($this->unit);
  }

  /**
   * {@inheritdoc}
   */
  public function setValue($values, $notify = TRUE) {
    // Allow callers to pass a Measurement value object as the field item value.
    if ($values instanceof Measurement) {
      $measurement = $values;
      $values = [
        'number' => $measurement->getNumber(),
        'unit' => $measurement->getUnit(),
      ];
    }
    parent::setValue($values, $notify);
  }

bojanz's avatar
bojanz committed
107
  /**
bojanz's avatar
bojanz committed
108 109 110
   * {@inheritdoc}
   */
  public static function defaultStorageSettings() {
bojanz's avatar
bojanz committed
111
    return [
bojanz's avatar
bojanz committed
112
      'measurement_type' => MeasurementType::LENGTH,
bojanz's avatar
bojanz committed
113
    ] + parent::defaultStorageSettings();
bojanz's avatar
bojanz committed
114 115 116 117 118 119
  }

  /**
   * {@inheritdoc}
   */
  public function storageSettingsForm(array &$form, FormStateInterface $form_state, $has_data) {
bojanz's avatar
bojanz committed
120
    $element['measurement_type'] = [
bojanz's avatar
bojanz committed
121 122 123 124 125 126
      '#type' => 'radios',
      '#title' => t('Measurement type'),
      '#options' => MeasurementType::getLabels(),
      '#default_value' => $this->getSetting('measurement_type'),
      '#required' => TRUE,
      '#disabled' => $has_data,
bojanz's avatar
bojanz committed
127
    ];
bojanz's avatar
bojanz committed
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143

    return $element;
  }

  /**
   * {@inheritdoc}
   */
  public static function getPreconfiguredOptions() {
    $options = [];
    // Expose an individual field in the Field UI for each measurement type.
    foreach (MeasurementType::getLabels() as $type => $label) {
      $options[$type] = [
        'label' => $label,
        'field_storage_config' => [
          'settings' => [
            'measurement_type' => $type,
bojanz's avatar
bojanz committed
144
          ],
bojanz's avatar
bojanz committed
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
        ],
      ];
    }

    return $options;
  }

  /**
   * Gets the Measurement value object for the current field item.
   *
   * @return \Drupal\physical\Measurement
   *   A subclass of Measurement (Length, Volume, etc).
   */
  public function toMeasurement() {
    $class = MeasurementType::getClass($this->getSetting('measurement_type'));
    return new $class($this->number, $this->unit);
  }

}