vendor/easycorp/easyadmin-bundle/src/Collection/FieldCollection.php line 123

Open in your IDE?
  1. <?php
  2. namespace EasyCorp\Bundle\EasyAdminBundle\Collection;
  3. use EasyCorp\Bundle\EasyAdminBundle\Contracts\Collection\CollectionInterface;
  4. use EasyCorp\Bundle\EasyAdminBundle\Contracts\Field\FieldInterface;
  5. use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto;
  6. use EasyCorp\Bundle\EasyAdminBundle\Field\Field;
  7. /**
  8. * @author Javier Eguiluz <javier.eguiluz@gmail.com>
  9. */
  10. final class FieldCollection implements CollectionInterface
  11. {
  12. /** @var FieldDto[] */
  13. private $fields;
  14. /**
  15. * @param FieldInterface[]|string[] $fields
  16. */
  17. private function __construct(iterable $fields)
  18. {
  19. $this->fields = $this->processFields($fields);
  20. }
  21. public function __clone()
  22. {
  23. $clonedFields = [];
  24. foreach ($this->fields as $fieldDto) {
  25. $clonedFieldDto = clone $fieldDto;
  26. $clonedFields[$clonedFieldDto->getUniqueId()] = $clonedFieldDto;
  27. }
  28. $this->fields = $clonedFields;
  29. }
  30. /**
  31. * @param FieldInterface[]|string[] $fields
  32. */
  33. public static function new(iterable $fields): self
  34. {
  35. return new self($fields);
  36. }
  37. public function get(string $fieldUniqueId): ?FieldDto
  38. {
  39. return $this->fields[$fieldUniqueId] ?? null;
  40. }
  41. /**
  42. * It returns the first field associated to the given property or null if none found.
  43. * Some pages (index/detail) can render the same field more than once.
  44. * In those cases, this method always returns the first field occurrence.
  45. */
  46. public function getByProperty(string $propertyName): ?FieldDto
  47. {
  48. foreach ($this->fields as $field) {
  49. if ($propertyName === $field->getProperty()) {
  50. return $field;
  51. }
  52. }
  53. return null;
  54. }
  55. public function set(FieldDto $newOrUpdatedField): void
  56. {
  57. $this->fields[$newOrUpdatedField->getUniqueId()] = $newOrUpdatedField;
  58. }
  59. public function unset(FieldDto $removedField): void
  60. {
  61. unset($this->fields[$removedField->getUniqueId()]);
  62. }
  63. public function prepend(FieldDto $newField): void
  64. {
  65. $this->fields = array_merge([$newField->getUniqueId() => $newField], $this->fields);
  66. }
  67. public function first(): ?FieldDto
  68. {
  69. if (empty($this->fields)) {
  70. return null;
  71. }
  72. return $this->fields[array_key_first($this->fields)];
  73. }
  74. public function isEmpty(): bool
  75. {
  76. return 0 === \count($this->fields);
  77. }
  78. public function offsetExists($offset): bool
  79. {
  80. return \array_key_exists($offset, $this->fields);
  81. }
  82. public function offsetGet($offset)
  83. {
  84. return $this->fields[$offset];
  85. }
  86. public function offsetSet($offset, $value): void
  87. {
  88. $this->fields[$offset] = $value;
  89. }
  90. public function offsetUnset($offset): void
  91. {
  92. unset($this->fields[$offset]);
  93. }
  94. public function count(): int
  95. {
  96. return \count($this->fields);
  97. }
  98. /**
  99. * @return \ArrayIterator|\Traversable|FieldDto[]
  100. */
  101. public function getIterator()
  102. {
  103. return new \ArrayIterator($this->fields);
  104. }
  105. /**
  106. * @param FieldInterface[]|string[] $fields
  107. *
  108. * @return FieldDto[]
  109. */
  110. private function processFields(iterable $fields): array
  111. {
  112. $dtos = [];
  113. // for DX reasons, fields can be configured as a FieldInterface object and
  114. // as a simple string with the name of the Doctrine property
  115. /** @var FieldInterface|string $field */
  116. foreach ($fields as $field) {
  117. if (\is_string($field)) {
  118. $field = Field::new($field);
  119. }
  120. $dto = $field->getAsDto();
  121. if (null === $dto->getFieldFqcn()) {
  122. $dto->setFieldFqcn(\get_class($field));
  123. }
  124. $dtos[$dto->getUniqueId()] = $dto;
  125. }
  126. return $dtos;
  127. }
  128. }