ComputedItemListTrait.php 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. <?php
  2. namespace Drupal\Core\TypedData;
  3. /**
  4. * Provides common functionality for computed item lists.
  5. *
  6. * @see \Drupal\Core\TypedData\ListInterface
  7. * @see \Drupal\Core\TypedData\Plugin\DataType\ItemList
  8. * @see \Drupal\Core\Field\FieldItemListInterface
  9. * @see \Drupal\Core\Field\FieldItemList
  10. *
  11. * @ingroup typed_data
  12. */
  13. trait ComputedItemListTrait {
  14. /**
  15. * Whether the values have already been computed or not.
  16. *
  17. * @var bool
  18. */
  19. protected $valueComputed = FALSE;
  20. /**
  21. * Computes the values for an item list.
  22. */
  23. abstract protected function computeValue();
  24. /**
  25. * Ensures that values are only computed once.
  26. */
  27. protected function ensureComputedValue() {
  28. if ($this->valueComputed === FALSE) {
  29. $this->computeValue();
  30. $this->valueComputed = TRUE;
  31. }
  32. }
  33. /**
  34. * {@inheritdoc}
  35. */
  36. public function getValue() {
  37. $this->ensureComputedValue();
  38. return parent::getValue();
  39. }
  40. /**
  41. * {@inheritdoc}
  42. */
  43. public function setValue($values, $notify = TRUE) {
  44. parent::setValue($values, $notify);
  45. // Make sure that subsequent getter calls do not try to compute the values
  46. // again.
  47. $this->valueComputed = TRUE;
  48. }
  49. /**
  50. * {@inheritdoc}
  51. */
  52. public function getString() {
  53. $this->ensureComputedValue();
  54. return parent::getString();
  55. }
  56. /**
  57. * {@inheritdoc}
  58. */
  59. public function get($index) {
  60. if (!is_numeric($index)) {
  61. throw new \InvalidArgumentException('Unable to get a value with a non-numeric delta in a list.');
  62. }
  63. // Unlike the base implementation of
  64. // \Drupal\Core\TypedData\ListInterface::get(), we do not add an empty item
  65. // automatically because computed item lists need to behave like
  66. // non-computed ones. For example, calling isEmpty() on a computed item list
  67. // should return TRUE when the values were computed and the item list is
  68. // truly empty.
  69. // @see \Drupal\Core\TypedData\Plugin\DataType\ItemList::get().
  70. $this->ensureComputedValue();
  71. return isset($this->list[$index]) ? $this->list[$index] : NULL;
  72. }
  73. /**
  74. * {@inheritdoc}
  75. */
  76. public function set($index, $value) {
  77. $this->ensureComputedValue();
  78. return parent::set($index, $value);
  79. }
  80. /**
  81. * {@inheritdoc}
  82. */
  83. public function appendItem($value = NULL) {
  84. $this->ensureComputedValue();
  85. return parent::appendItem($value);
  86. }
  87. /**
  88. * {@inheritdoc}
  89. */
  90. public function removeItem($index) {
  91. $this->ensureComputedValue();
  92. return parent::removeItem($index);
  93. }
  94. /**
  95. * {@inheritdoc}
  96. */
  97. public function isEmpty() {
  98. $this->ensureComputedValue();
  99. return parent::isEmpty();
  100. }
  101. /**
  102. * {@inheritdoc}
  103. */
  104. public function offsetExists($offset) {
  105. $this->ensureComputedValue();
  106. return parent::offsetExists($offset);
  107. }
  108. /**
  109. * {@inheritdoc}
  110. */
  111. public function getIterator() {
  112. $this->ensureComputedValue();
  113. return parent::getIterator();
  114. }
  115. /**
  116. * {@inheritdoc}
  117. */
  118. public function count() {
  119. $this->ensureComputedValue();
  120. return parent::count();
  121. }
  122. /**
  123. * {@inheritdoc}
  124. */
  125. public function applyDefaultValue($notify = TRUE) {
  126. // Default values do not make sense for computed item lists. However, this
  127. // method can be overridden if needed.
  128. return $this;
  129. }
  130. }