ItemList.php

Contains \Drupal\Core\TypedData\List.

Namespace

Drupal\Core\TypedData

File

drupal/core/lib/Drupal/Core/TypedData/ItemList.php
View source
<?php

/**
 * @file
 * Contains \Drupal\Core\TypedData\List.
 */
namespace Drupal\Core\TypedData;


/**
 * A generic list class.
 *
 * This class can serve as list for any type of items.
 * Note: The class cannot be called "List" as list is a reserved PHP keyword.
 */
class ItemList extends TypedData implements \IteratorAggregate, ListInterface {

  /**
   * Numerically indexed array items.
   *
   * @var array
   */
  protected $list = array();

  /**
   * Overrides \Drupal\Core\TypedData\TypedData::getValue().
   */
  public function getValue() {
    if (isset($this->list)) {
      $values = array();
      foreach ($this->list as $delta => $item) {
        $values[$delta] = $item
          ->getValue();
      }
      return $values;
    }
  }

  /**
   * Overrides \Drupal\Core\TypedData\TypedData::setValue().
   *
   * @param array|null $values
   *   An array of values of the field items, or NULL to unset the field.
   */
  public function setValue($values, $notify = TRUE) {

    // Notify the parent of any changes to be made.
    if ($notify && isset($this->parent)) {
      $this->parent
        ->onChange($this->name);
    }
    if (!isset($values) || $values === array()) {
      $this->list = $values;
    }
    else {
      if (!is_array($values)) {
        throw new \InvalidArgumentException('Cannot set a list with a non-array value.');
      }

      // Clear the values of properties for which no value has been passed.
      if (isset($this->list)) {
        $this->list = array_intersect_key($this->list, $values);
      }

      // Set the values.
      foreach ($values as $delta => $value) {
        if (!is_numeric($delta)) {
          throw new \InvalidArgumentException('Unable to set a value with a non-numeric delta in a list.');
        }
        elseif (!isset($this->list[$delta])) {
          $this->list[$delta] = $this
            ->createItem($delta, $value);
        }
        else {
          $this->list[$delta]
            ->setValue($value);
        }
      }
    }
  }

  /**
   * Overrides \Drupal\Core\TypedData\TypedData::getString().
   */
  public function getString() {
    $strings = array();
    if (isset($this->list)) {
      foreach ($this->list as $item) {
        $strings[] = $item
          ->getString();
      }

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

  /**
   * Overrides \Drupal\Core\TypedData\TypedData::getConstraints().
   */
  public function getConstraints() {

    // Apply the constraints to the list items only.
    return array();
  }

  /**
   * Implements \ArrayAccess::offsetExists().
   */
  public function offsetExists($offset) {
    return isset($this->list) && array_key_exists($offset, $this->list) && $this
      ->offsetGet($offset)
      ->getValue() !== NULL;
  }

  /**
   * Implements \ArrayAccess::offsetUnset().
   */
  public function offsetUnset($offset) {
    if (isset($this->list)) {
      unset($this->list[$offset]);
    }
  }

  /**
   * Implements \ArrayAccess::offsetGet().
   */
  public function offsetGet($offset) {
    if (!is_numeric($offset)) {
      throw new \InvalidArgumentException('Unable to get a value with a non-numeric delta in a list.');
    }
    elseif (!isset($this->list[$offset])) {
      $this->list[$offset] = $this
        ->createItem($offset);
    }
    return $this->list[$offset];
  }

  /**
   * Helper for creating a list item object.
   *
   * @return \Drupal\Core\TypedData\TypedDataInterface
   */
  protected function createItem($offset = 0, $value = NULL) {
    return \Drupal::typedData()
      ->getPropertyInstance($this, $offset, $value);
  }

  /**
   * Implements \Drupal\Core\TypedData\ListInterface::getItemDefinition().
   */
  public function getItemDefinition() {
    return array(
      'list' => FALSE,
    ) + $this->definition;
  }

  /**
   * Implements \ArrayAccess::offsetSet().
   */
  public function offsetSet($offset, $value) {
    if (!isset($offset)) {

      // The [] operator has been used so point at a new entry.
      $offset = $this->list ? max(array_keys($this->list)) + 1 : 0;
    }
    if (is_numeric($offset)) {

      // Support setting values via typed data objects.
      if ($value instanceof TypedDataInterface) {
        $value = $value
          ->getValue();
      }
      $this
        ->offsetGet($offset)
        ->setValue($value);
    }
    else {
      throw new \InvalidArgumentException('Unable to set a value with a non-numeric delta in a list.');
    }
  }

  /**
   * Implements \IteratorAggregate::getIterator().
   */
  public function getIterator() {
    if (isset($this->list)) {
      return new \ArrayIterator($this->list);
    }
    return new \ArrayIterator(array());
  }

  /**
   * Implements \Countable::count().
   */
  public function count() {
    return isset($this->list) ? count($this->list) : 0;
  }

  /**
   * Implements \Drupal\Core\TypedData\ListInterface::isEmpty().
   */
  public function isEmpty() {
    if (isset($this->list)) {
      foreach ($this->list as $item) {
        if ($item instanceof ComplexDataInterface || $item instanceof ListInterface) {
          if (!$item
            ->isEmpty()) {
            return FALSE;
          }
        }
        elseif ($item
          ->getValue() !== NULL) {
          return FALSE;
        }
      }
    }
    return TRUE;
  }

  /**
   * Implements \Drupal\Core\TypedData\ListInterface::onChange().
   */
  public function onChange($delta) {

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

  /**
   * Magic method: Implements a deep clone.
   */
  public function __clone() {
    if (isset($this->list)) {
      foreach ($this->list as $delta => $item) {
        $this->list[$delta] = clone $item;
        $this->list[$delta]
          ->setContext($delta, $this);
      }
    }
  }

}

Classes

Namesort descending Description
ItemList A generic list class.