1<?php 2 3 4namespace ComboStrap; 5 6 7use ComboStrap\Meta\Api\Metadata; 8use ComboStrap\Meta\Api\MetadataStore; 9 10class MetadataStoreTransfer 11{ 12 const CANONICAL = "meta-store-transfer"; 13 14 /** 15 * @var MetadataStore 16 */ 17 private $sourceStore; 18 /** 19 * @var MetadataStore 20 */ 21 private $targetStore; 22 23 /** 24 * @var MarkupPath 25 */ 26 private $page; 27 28 29 /** 30 * @var array - the processing messages 31 */ 32 private array $messages = []; 33 34 /** 35 * @var array - the validated metadata (that may be stored) 36 */ 37 private array $metadatasThatMayBeStored; 38 39 /** 40 * @var Metadata[] - the original metas (no default as we check if they were already set) 41 */ 42 private array $originalMetadatas; 43 44 /** 45 * MetadataStoreTransfer constructor. 46 * @param MarkupPath $resource 47 */ 48 public function __construct(ResourceCombo $resource) 49 { 50 $this->page = $resource; 51 } 52 53 54 public static function createForPage($page): MetadataStoreTransfer 55 { 56 return new MetadataStoreTransfer($page); 57 } 58 59 /** 60 * @return $this - validate the transfer (ie the metadatas). The metadata that can be retrieved via {@link self::getValidatedMetadatas()} 61 * and the bad validation messages if any via {@link self::getMessages()} 62 */ 63 public function validate(): MetadataStoreTransfer 64 { 65 66 if (isset($this->metadatasThatMayBeStored)) { 67 return $this; 68 } 69 if (!isset($this->originalMetadatas)) { 70 throw new ExceptionRuntimeInternal("The original metadata should be defined"); 71 } 72 73 $this->metadatasThatMayBeStored = []; 74 foreach ($this->originalMetadatas as $originalMetaKey => $originalMetaValue) { 75 76 77 try { 78 $metadataObject = Meta\Api\MetadataSystem::getForName($originalMetaKey); 79 } catch (ExceptionNotFound $e) { 80 LogUtility::warning("The meta ($originalMetaKey) was not found", self::CANONICAL, $e); 81 continue; 82 } 83 84 /** 85 * Take old name or renaming into account 86 * 87 * ie The old key should be replace by the new one 88 * (ie {@link \ComboStrap\PagePublicationDate::OLD_META_KEY} 89 * by {@link \ComboStrap\PagePublicationDate::PROPERTY_NAME} 90 */ 91 $name = $originalMetaKey; 92 if ($metadataObject !== null) { 93 $name = $metadataObject::getName(); 94 $originalMetaKey = $metadataObject::getPersistentName(); 95 } 96 97 /** 98 * Not modifiable meta check 99 */ 100 if (in_array($name, Metadata::NOT_MODIFIABLE_METAS)) { 101 $this->messages[] = Message::createWarningMessage("The metadata ($name) is a protected metadata and cannot be modified") 102 ->setCanonical(Metadata::CANONICAL); 103 continue; 104 } 105 106 /** 107 * Unknown meta 108 */ 109 if ($metadataObject === null) { 110 $this->messages[] = Message::createWarningMessage("The metadata ($originalMetaKey) is unknown and was not persisted")->setCanonical(Metadata::CANONICAL); 111 continue; 112 } 113 114 115 /** 116 * We build and not set with {@link Metadata::setFromStoreValue()} 117 * because tabular data in forms have several key by columns (ie on key is a column 118 * that may have several values) 119 * Therefore tabular data needs to get access to the whole source store 120 * to be build 121 */ 122 $metadataObject 123 ->setResource($this->page) 124 ->setReadStore($this->sourceStore) 125 ->setWriteStore($this->targetStore) 126 ->buildFromReadStore(); 127 128 $this->metadatasThatMayBeStored[$name] = $metadataObject; 129 130 } 131 return $this; 132 } 133 134 public function fromStore(MetadataStore $sourceStore): MetadataStoreTransfer 135 { 136 $this->sourceStore = $sourceStore; 137 return $this; 138 } 139 140 public function toStore(MetadataStore $targetStore): MetadataStoreTransfer 141 { 142 $this->targetStore = $targetStore; 143 return $this; 144 } 145 146 /** 147 * @param Metadata[]|null $data - the metadadata (@deprecate for {@link self::setMetadatas()} 148 * @return $this 149 */ 150 public function process(array $data = null): MetadataStoreTransfer 151 { 152 153 /** 154 * We may use this object to validate, setting before the processing 155 */ 156 if (isset($this->originalMetadatas) && $data !== null) { 157 throw new ExceptionRuntimeInternal("The metadata to process were already set"); 158 } else { 159 $this->originalMetadatas = $data; 160 } 161 $messages = []; 162 163 /** 164 * Pre-processing 165 * Check/ validity and list of metadata building 166 */ 167 $validatedMetadata = $this->validate()->getValidatedMetadatas(); 168 169 foreach ($validatedMetadata as $metadata) { 170 171 /** 172 * Persistent ? 173 */ 174 if ($metadata->getPersistenceType() !== Metadata::PERSISTENT_METADATA) { 175 $messages[] = Message::createWarningMessage("The metadata ({$metadata->getName()}) is not persistent and cannot be modified") 176 ->setCanonical($metadata->getCanonical()); 177 continue; 178 } 179 180 /** 181 * Sync 182 */ 183 try { 184 $metadata->sendToWriteStore(); 185 } catch (ExceptionCompile $e) { 186 $messages[] = Message::createErrorMessage("Error while replicating the meta ($metadata) from the store ($this->sourceStore) to the store ($this->targetStore). Message: " . $e->getMessage()) 187 ->setCanonical($metadata->getCanonical()); 188 } 189 } 190 $this->targetStore->persist(); 191 192 $this->messages = $messages; 193 return $this; 194 } 195 196 /** 197 * @return Message[] 198 */ 199 public function getMessages(): array 200 { 201 return $this->messages; 202 } 203 204 205 /** 206 * @return Metadata[] - an array where the key is the name and the value a {@link Metadata} object 207 */ 208 public function getValidatedMetadatas(): array 209 { 210 if (!isset($this->metadatasThatMayBeStored)) { 211 $this->validate(); 212 } 213 return $this->metadatasThatMayBeStored; 214 } 215 216 /** 217 * @param Metadata[] $originalMetadatas 218 * @return $this 219 */ 220 public function setMetadatas(array $originalMetadatas): MetadataStoreTransfer 221 { 222 $this->originalMetadatas = $originalMetadatas; 223 return $this; 224 } 225 226 227} 228