vendor/ibexa/core/src/lib/Persistence/Legacy/Content/Mapper/ResolveVirtualFieldSubscriber.php line 78

Open in your IDE?
  1. <?php
  2. /**
  3. * @copyright Copyright (C) Ibexa AS. All rights reserved.
  4. * @license For full copyright and license information view LICENSE file distributed with this source code.
  5. */
  6. declare(strict_types=1);
  7. namespace Ibexa\Core\Persistence\Legacy\Content\Mapper;
  8. use Ibexa\Contracts\Core\Event\Mapper\ResolveMissingFieldEvent;
  9. use Ibexa\Contracts\Core\FieldType\DefaultDataFieldStorage;
  10. use Ibexa\Contracts\Core\Persistence\Content\Field;
  11. use Ibexa\Contracts\Core\Persistence\Content\FieldValue;
  12. use Ibexa\Contracts\Core\Persistence\Content\Type\FieldDefinition;
  13. use Ibexa\Contracts\Core\Persistence\Content\VersionInfo;
  14. use Ibexa\Core\FieldType\NullStorage;
  15. use Ibexa\Core\Persistence\Legacy\Content\FieldValue\Converter\Exception\NotFound;
  16. use Ibexa\Core\Persistence\Legacy\Content\FieldValue\ConverterRegistry;
  17. use Ibexa\Core\Persistence\Legacy\Content\Gateway as ContentGateway;
  18. use Ibexa\Core\Persistence\Legacy\Content\StorageFieldValue;
  19. use Ibexa\Core\Persistence\Legacy\Content\StorageRegistry;
  20. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  21. final class ResolveVirtualFieldSubscriber implements EventSubscriberInterface
  22. {
  23. private ConverterRegistry $converterRegistry;
  24. private StorageRegistry $storageRegistry;
  25. private ContentGateway $contentGateway;
  26. public function __construct(
  27. ConverterRegistry $converterRegistry,
  28. StorageRegistry $storageRegistry,
  29. ContentGateway $contentGateway
  30. ) {
  31. $this->converterRegistry = $converterRegistry;
  32. $this->storageRegistry = $storageRegistry;
  33. $this->contentGateway = $contentGateway;
  34. }
  35. public static function getSubscribedEvents(): array
  36. {
  37. return [
  38. ResolveMissingFieldEvent::class => [
  39. ['persistExternalStorageField', -100],
  40. ['resolveVirtualExternalStorageField', -80],
  41. ['resolveVirtualField', 0],
  42. ],
  43. ];
  44. }
  45. public function resolveVirtualField(ResolveMissingFieldEvent $event): void
  46. {
  47. if ($event->getField()) {
  48. return;
  49. }
  50. $content = $event->getContent();
  51. try {
  52. $emptyField = $this->createEmptyField(
  53. $content->versionInfo,
  54. $event->getFieldDefinition(),
  55. $event->getLanguageCode()
  56. );
  57. $event->setField($emptyField);
  58. } catch (NotFound $exception) {
  59. return;
  60. }
  61. }
  62. /**
  63. * @throws \Ibexa\Core\Persistence\Legacy\Content\FieldValue\Converter\Exception\NotFound
  64. */
  65. public function persistExternalStorageField(ResolveMissingFieldEvent $event): void
  66. {
  67. $field = $event->getField();
  68. if ($field === null) {
  69. // Nothing to persist
  70. return;
  71. }
  72. if ($field->id !== null) {
  73. // Not a virtual field
  74. return;
  75. }
  76. $fieldDefinition = $event->getFieldDefinition();
  77. $storage = $this->storageRegistry->getStorage($fieldDefinition->fieldType);
  78. if ($storage instanceof NullStorage) {
  79. // Not an external storage
  80. return;
  81. }
  82. $content = $event->getContent();
  83. $field->id = $this->contentGateway->insertNewField(
  84. $content,
  85. $field,
  86. $this->getDefaultStorageValue()
  87. );
  88. if ($field->value->data !== null) {
  89. $result = $storage->storeFieldData(
  90. $content->versionInfo,
  91. $field,
  92. []
  93. );
  94. if ($result === true) {
  95. $storageValue = new StorageFieldValue();
  96. $converter = $this->converterRegistry->getConverter($fieldDefinition->fieldType);
  97. $converter->toStorageValue(
  98. $field->value,
  99. $storageValue
  100. );
  101. $this->contentGateway->updateField(
  102. $field,
  103. $storageValue
  104. );
  105. }
  106. }
  107. $storage->getFieldData(
  108. $content->versionInfo,
  109. $field,
  110. []
  111. );
  112. $event->setField($field);
  113. }
  114. public function resolveVirtualExternalStorageField(ResolveMissingFieldEvent $event): void
  115. {
  116. $field = $event->getField();
  117. if ($field === null) {
  118. // Nothing to resolve
  119. return;
  120. }
  121. if ($field->id !== null) {
  122. // Not a virtual field
  123. return;
  124. }
  125. $fieldDefinition = $event->getFieldDefinition();
  126. $storage = $this->storageRegistry->getStorage($fieldDefinition->fieldType);
  127. if ($storage instanceof NullStorage) {
  128. // Not an external storage
  129. return;
  130. }
  131. if (!$storage instanceof DefaultDataFieldStorage) {
  132. return;
  133. }
  134. $content = $event->getContent();
  135. $storage->getDefaultFieldData(
  136. $content->versionInfo,
  137. $field
  138. );
  139. $event->setField($field);
  140. // Do not persist the external storage field
  141. $event->stopPropagation();
  142. }
  143. /**
  144. * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException
  145. */
  146. private function createEmptyField(
  147. VersionInfo $versionInfo,
  148. FieldDefinition $fieldDefinition,
  149. string $languageCode
  150. ): Field {
  151. $field = new Field();
  152. $field->fieldDefinitionId = $fieldDefinition->id;
  153. $field->type = $fieldDefinition->fieldType;
  154. $field->value = $this->getDefaultValue($fieldDefinition);
  155. $field->languageCode = $languageCode;
  156. $field->versionNo = $versionInfo->versionNo;
  157. return $field;
  158. }
  159. /**
  160. * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException
  161. */
  162. private function getDefaultValue(FieldDefinition $fieldDefinition): FieldValue
  163. {
  164. $value = clone $fieldDefinition->defaultValue;
  165. $storageValue = $this->getDefaultStorageValue();
  166. $converter = $this->converterRegistry->getConverter($fieldDefinition->fieldType);
  167. $converter->toStorageValue($value, $storageValue);
  168. $converter->toFieldValue($storageValue, $value);
  169. return $value;
  170. }
  171. private function getDefaultStorageValue(): StorageFieldValue
  172. {
  173. $storageValue = new StorageFieldValue();
  174. $storageValue->dataFloat = 0;
  175. $storageValue->dataInt = 0;
  176. $storageValue->dataText = '';
  177. $storageValue->sortKeyInt = 0;
  178. $storageValue->sortKeyString = '';
  179. return $storageValue;
  180. }
  181. }