You are here

class SerialItem in Serial Field 8

Plugin implementation of the 'serial' field type.

@todo should not be translatable, by default

Plugin annotation


@FieldType(
  id = "serial",
  label = @Translation("Serial"),
  description = @Translation("Auto increment serial field type."),
  category = @Translation("Number"),
  default_widget = "serial_default_widget",
  default_formatter = "serial_default_formatter"
)

Hierarchy

Expanded class hierarchy of SerialItem

File

src/Plugin/Field/FieldType/SerialItem.php, line 25

Namespace

Drupal\serial\Plugin\Field\FieldType
View source
class SerialItem extends FieldItemBase {

  /**
   * {@inheritdoc}
   */
  public static function schema(FieldStorageDefinitionInterface $field) {
    return [
      'columns' => [
        'value' => [
          'type' => 'int',
          'unsigned' => TRUE,
          'not null' => TRUE,
          'sortable' => TRUE,
          'views' => TRUE,
          'index' => TRUE,
        ],
      ],
    ];
  }

  /**
   * {@inheritdoc}
   */
  public static function defaultStorageSettings() {
    return [
      'start_value' => 1,
      'init_existing_entities' => 0,
    ] + parent::defaultStorageSettings();
  }

  /**
   * {@inheritdoc}
   */
  public function storageSettingsForm(array &$form, FormStateInterface $form_state, $has_data) {
    $element = [];
    $element['start_value'] = [
      '#type' => 'number',
      '#title' => $this
        ->t('Starting value'),
      '#default_value' => $this
        ->getSetting('start_value'),
      '#min' => 1,
      '#required' => TRUE,
      '#disabled' => $has_data,
    ];
    $element['init_existing_entities'] = [
      '#type' => 'radios',
      '#title' => $this
        ->t('Start on existing entities'),
      '#description' => $this
        ->t('When this field is created for a bundle that already have entities.'),
      '#options' => [
        0 => $this
          ->t('No'),
        1 => $this
          ->t('Yes'),
      ],
      '#default_value' => $this
        ->getSetting('init_existing_entities'),
      '#required' => TRUE,
      '#disabled' => $has_data,
    ];

    // Only run the initialization when the field has no data.
    if (!$has_data) {

      // @todo ideally, use submit handler and not validate
      // $handlers = $form_state->getSubmitHandlers();
      // $handlers[] = [$this, 'initializeEntitiesCallback'];
      // $form_state->setSubmitHandlers($handlers);
      $form['#validate'][] = [
        $this,
        'initializeEntitiesCallback',
      ];
    }
    return $element;
  }

  /**
   * Initialize entities depending on the storage settings.
   *
   * @param array $form
   *   The form where the settings form is being included in.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state of the (entire) configuration form.
   */
  public function initializeEntitiesCallback(array &$form, FormStateInterface $form_state) {

    // Check if existing entities have to be initialized.
    $settings = $form_state
      ->getValue('settings');
    if ((int) $settings['init_existing_entities'] === 1) {
      $startValue = (int) $settings['start_value'];

      // Check then first if the bundle has entities.
      $fieldConfig = $this
        ->getFieldDefinition();
      $entityTypeId = $fieldConfig
        ->getTargetEntityTypeId();
      $storage = \Drupal::entityTypeManager()
        ->getStorage($entityTypeId);
      $bundleKey = $storage
        ->getEntityType()
        ->getKey('bundle');
      $bundle = $fieldConfig
        ->getTargetBundle();
      $query = \Drupal::entityQuery($entityTypeId);
      $query
        ->condition($bundleKey, $bundle);
      $ids = $query
        ->execute();
      if (count($ids) > 0) {

        /** @var \Drupal\serial\SerialStorageInterface $serialStorage */
        $serialStorage = \Drupal::getContainer()
          ->get('serial.sql_storage');

        // Set serial values for existing entities.
        $oldCount = $serialStorage
          ->initOldEntries($entityTypeId, $bundle, $fieldConfig
          ->getFieldStorageDefinition()
          ->getName(), $startValue);
        if ($oldCount > 0) {
          \Drupal::messenger()
            ->addMessage(t('Serial values have been automatically set for %count existing entities, starting from %start_value.', [
            '%count' => $oldCount,
            '%start_value' => $startValue,
          ]));
        }
      }
      else {
        \Drupal::messenger()
          ->addWarning(t('No entities to initialize, the next entity to be created will start from %start_value.', [
          '%start_value' => $startValue,
        ]));
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public function getValue() {

    // Update the values and return them.
    foreach ($this->properties as $name => $property) {
      $value = $property
        ->getValue();

      // Only write NULL values if the whole map is not NULL.
      if (isset($this->values) || isset($value)) {
        $this->values[$name] = $value;
      }
    }
    return $this->values;
  }

  /**
   * {@inheritdoc}
   */
  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {

    // @todo review DataDefinition methods : setReadOnly, setComputed, setRequired, setConstraints
    $properties['value'] = DataDefinition::create('integer')
      ->setLabel(t('Serial'))
      ->setComputed(TRUE)
      ->setInternal(FALSE)
      ->setRequired(TRUE);
    return $properties;
  }

  /**
   * {@inheritdoc}
   */
  public function isEmpty() {
    $value = $this
      ->get('value')
      ->getValue();

    // For numbers, the field is empty if the value isn't numeric.
    // But should never be treated as empty.
    $empty = $value === NULL || !is_numeric($value);
    return $empty;
  }

  /**
   * {@inheritdoc}
   */
  public function preSave() {
    $value = $this
      ->getSerial();
    if (isset($value)) {
      $this
        ->setValue($value);
    }
  }

  /**
   * Gets the serial for this entity type, bundle, field instance.
   *
   * @return int
   *   serial id
   */
  private function getSerial() {
    $serial = NULL;
    $entity = $this
      ->getEntity();
    $newSerial = FALSE;

    // Does not apply if the node is not new or translated.
    if ($entity
      ->isNew()) {
      $newSerial = TRUE;
    }
    else {

      // Handle entity translation: fetch the same id or another one
      // depending of what is the design.
      // This should probably be solved by the end user decision
      // while setting the field translation.

      /** @var \Drupal\Core\Language\LanguageManagerInterface $languageManager */
      $languageManager = \Drupal::getContainer()
        ->get('language_manager');

      // @todo isMultilingual is global, prefer local hasTranslation
      if ($languageManager
        ->isMultilingual() && $entity instanceof TranslatableInterface) {
        $newSerial = $entity
          ->isNewTranslation();
      }
    }
    if ($newSerial) {

      /** @var \Drupal\serial\SerialStorageInterface $serialStorage */
      $serialStorage = \Drupal::getContainer()
        ->get('serial.sql_storage');
      $serial = $serialStorage
        ->generateValue($this
        ->getFieldDefinition(), $this
        ->getEntity());

      // Get the starting value from the storage settings.
      $settings = $this
        ->getSettings();
      $startValue = isset($settings['start_value']) ? $settings['start_value'] : 1;

      // Subtract one as it is already added in code above.
      $serial = $serial + $startValue - 1;
    }
    return $serial;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
DependencySerializationTrait::$_entityStorages protected property An array of entity type IDs keyed by the property name of their storages.
DependencySerializationTrait::$_serviceIds protected property An array of service IDs keyed by property name used for serialization.
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
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::defaultFieldSettings public static function Defines the field-level settings for this plugin. Overrides FieldItemInterface::defaultFieldSettings 7
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::fieldSettingsForm public function Returns a form for the field-level settings. Overrides FieldItemInterface::fieldSettingsForm 7
FieldItemBase::fieldSettingsFromConfigData public static function Returns a settings array in the field type's canonical representation. Overrides FieldItemInterface::fieldSettingsFromConfigData 1
FieldItemBase::fieldSettingsToConfigData public static function Returns a settings array that can be stored as a configuration value. Overrides FieldItemInterface::fieldSettingsToConfigData 1
FieldItemBase::generateSampleValue public static function Generates placeholder field values. Overrides FieldItemInterface::generateSampleValue 18
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::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::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.
SerialItem::defaultStorageSettings public static function Defines the storage-level settings for this plugin. Overrides FieldItemBase::defaultStorageSettings
SerialItem::getSerial private function Gets the serial for this entity type, bundle, field instance.
SerialItem::getValue public function Gets the data value. Overrides Map::getValue
SerialItem::initializeEntitiesCallback public function Initialize entities depending on the storage settings.
SerialItem::isEmpty public function Determines whether the data structure is empty. Overrides Map::isEmpty
SerialItem::preSave public function Defines custom presave behavior for field values. Overrides FieldItemBase::preSave
SerialItem::propertyDefinitions public static function Defines field item properties. Overrides FieldItemInterface::propertyDefinitions
SerialItem::schema public static function Returns the schema for the field. Overrides FieldItemInterface::schema
SerialItem::storageSettingsForm public function Returns a form for the storage-level settings. Overrides FieldItemBase::storageSettingsForm
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
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::getConstraints public function Gets a list of validation constraints. Overrides TypedDataInterface::getConstraints 9
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