You are here

class Map in Drupal 9

Same name and namespace in other branches
  1. 8 core/lib/Drupal/Core/TypedData/Plugin/DataType/Map.php \Drupal\Core\TypedData\Plugin\DataType\Map
  2. 10 core/lib/Drupal/Core/TypedData/Plugin/DataType/Map.php \Drupal\Core\TypedData\Plugin\DataType\Map

The "map" data type.

The "map" data type represent a simple complex data type, e.g. for representing associative arrays. It can also serve as base class for any complex data type.

By default there is no metadata for contained properties. Extending classes may want to override MapDataDefinition::getPropertyDefinitions() to define it.

Plugin annotation


@DataType(
  id = "map",
  label = @Translation("Map"),
  definition_class = "\Drupal\Core\TypedData\MapDataDefinition"
)

Hierarchy

Expanded class hierarchy of Map

Related topics

1 file declares its use of Map
FieldItemBase.php in core/lib/Drupal/Core/Field/FieldItemBase.php

File

core/lib/Drupal/Core/TypedData/Plugin/DataType/Map.php, line 27

Namespace

Drupal\Core\TypedData\Plugin\DataType
View source
class Map extends TypedData implements \IteratorAggregate, ComplexDataInterface {

  /**
   * The data definition.
   *
   * @var \Drupal\Core\TypedData\ComplexDataDefinitionInterface
   */
  protected $definition;

  /**
   * An array of values for the contained properties.
   *
   * @var array
   */
  protected $values = [];

  /**
   * The array of properties.
   *
   * @var \Drupal\Core\TypedData\TypedDataInterface[]
   */
  protected $properties = [];

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

    // Update the values and return them.
    foreach ($this->properties as $name => $property) {
      $definition = $property
        ->getDataDefinition();
      if (!$definition
        ->isComputed()) {
        $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;
  }

  /**
   * Overrides \Drupal\Core\TypedData\TypedData::setValue().
   *
   * @param array|null $values
   *   An array of property values.
   * @param bool $notify
   *   (optional) Whether to notify the parent object of the change. Defaults to
   *   TRUE. If a property is updated from a parent object, set it to FALSE to
   *   avoid being notified again.
   */
  public function setValue($values, $notify = TRUE) {
    if (isset($values) && !is_array($values)) {
      throw new \InvalidArgumentException("Invalid values given. Values must be represented as an associative array.");
    }
    $this->values = $values;

    // Update any existing property objects.
    foreach ($this->properties as $name => $property) {
      $value = isset($values[$name]) ? $values[$name] : NULL;
      $property
        ->setValue($value, FALSE);

      // Remove the value from $this->values to ensure it does not contain any
      // value for computed properties.
      unset($this->values[$name]);
    }

    // Notify the parent of any changes.
    if ($notify && isset($this->parent)) {
      $this->parent
        ->onChange($this->name);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function getString() {
    $strings = [];
    foreach ($this
      ->getProperties() as $property) {
      $strings[] = $property
        ->getString();
    }

    // Remove any empty strings resulting from empty items.
    return implode(', ', array_filter($strings, 'mb_strlen'));
  }

  /**
   * {@inheritdoc}
   */
  public function get($property_name) {
    if (!isset($this->properties[$property_name])) {
      $value = NULL;
      if (isset($this->values[$property_name])) {
        $value = $this->values[$property_name];
      }

      // If the property is unknown, this will throw an exception.
      $this->properties[$property_name] = $this
        ->getTypedDataManager()
        ->getPropertyInstance($this, $property_name, $value);
    }
    return $this->properties[$property_name];
  }

  /**
   * {@inheritdoc}
   */
  public function set($property_name, $value, $notify = TRUE) {

    // Separate the writing in a protected method, such that onChange
    // implementations can make use of it.
    $this
      ->writePropertyValue($property_name, $value);
    $this
      ->onChange($property_name, $notify);
    return $this;
  }

  /**
   * Writes the value of a property without handling changes.
   *
   * Implementations of onChange() should use this method instead of set() in
   * order to avoid onChange() being triggered again.
   *
   * @param string $property_name
   *   The name of the property to be written.
   * @param $value
   *   The value to set.
   */
  protected function writePropertyValue($property_name, $value) {
    if ($this->definition
      ->getPropertyDefinition($property_name)) {
      $this
        ->get($property_name)
        ->setValue($value, FALSE);
    }
    else {

      // Just set the plain value, which allows adding a new entry to the map.
      $this->values[$property_name] = $value;
    }
  }

  /**
   * {@inheritdoc}
   */
  public function getProperties($include_computed = FALSE) {
    $properties = [];
    foreach ($this->definition
      ->getPropertyDefinitions() as $name => $definition) {
      if ($include_computed || !$definition
        ->isComputed()) {
        $properties[$name] = $this
          ->get($name);
      }
    }
    return $properties;
  }

  /**
   * {@inheritdoc}
   */
  public function toArray() {
    $values = [];
    foreach ($this
      ->getProperties() as $name => $property) {
      $values[$name] = $property
        ->getValue();
    }
    return $values;
  }

  /**
   * {@inheritdoc}
   */
  public function getIterator() {
    return new \ArrayIterator($this
      ->getProperties());
  }

  /**
   * {@inheritdoc}
   */
  public function isEmpty() {
    foreach ($this->properties as $property) {
      $definition = $property
        ->getDataDefinition();
      if (!$definition
        ->isComputed() && $property
        ->getValue() !== NULL) {
        return FALSE;
      }
    }
    if (isset($this->values)) {
      foreach ($this->values as $name => $value) {
        if (isset($value) && !isset($this->properties[$name])) {
          return FALSE;
        }
      }
    }
    return TRUE;
  }

  /**
   * Magic method: Implements a deep clone.
   */
  public function __clone() {
    foreach ($this->properties as $name => $property) {
      $this->properties[$name] = clone $property;
      $this->properties[$name]
        ->setContext($name, $this);
    }
  }

  /**
   * {@inheritdoc}
   *
   * @param $property_name
   *   The name of the property.
   * @param bool $notify
   *   (optional) Whether to forward the notification to the parent. Defaults to
   *   TRUE. By passing FALSE, overrides of this method can re-use the logic
   *   of parent classes without triggering notification.
   */
  public function onChange($property_name, $notify = TRUE) {

    // Notify the parent of changes.
    if ($notify && isset($this->parent)) {
      $this->parent
        ->onChange($this->name);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function applyDefaultValue($notify = TRUE) {

    // Apply the default value of all properties.
    foreach ($this
      ->getProperties() as $property) {
      $property
        ->applyDefaultValue(FALSE);
    }
    return $this;
  }

}

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
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::isEmpty public function Determines whether the data structure is empty. Overrides ComplexDataInterface::isEmpty 17
Map::onChange public function Overrides TraversableTypedDataInterface::onChange 4
Map::set public function Sets a property value. Overrides ComplexDataInterface::set
Map::setValue public function Overrides \Drupal\Core\TypedData\TypedData::setValue(). Overrides TypedData::setValue 1
Map::toArray public function Returns an array of all property values. Overrides ComplexDataInterface::toArray 1
Map::writePropertyValue protected function Writes the value of a property without handling changes. 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::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
TypedData::__construct public function Constructs a TypedData object given its definition and context. 3
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