Exponential 5.x Kernel 7.5.40 Exponential New Stack (Symfony-based) Kernel — PHP Class Reference

FieldHandler.php
Go to the documentation of this file.
1 <?php
2
7 namespace eZ\Publish\Core\Persistence\Legacy\Content;
8
9 use eZ\Publish\SPI\Persistence\Content;
10 use eZ\Publish\SPI\Persistence\Content\Type;
11 use eZ\Publish\SPI\Persistence\Content\VersionInfo;
12 use eZ\Publish\SPI\Persistence\Content\Field;
13 use eZ\Publish\SPI\Persistence\Content\UpdateStruct;
14 use eZ\Publish\SPI\Persistence\Content\Type\FieldDefinition;
15 use eZ\Publish\Core\Persistence\FieldTypeRegistry;
16 use eZ\Publish\SPI\Persistence\Content\Language\Handler as LanguageHandler;
17
21 class FieldHandler
22 {
28 protected $contentGateway;
29
31 protected $languageHandler;
32
38 protected $mapper;
39
45 protected $storageHandler;
46
52 protected $fieldTypeRegistry;
53
59 protected $fieldTypes;
60
70 public function __construct(
71 Gateway $contentGateway,
72 Mapper $mapper,
73 StorageHandler $storageHandler,
74 LanguageHandler $languageHandler,
75 FieldTypeRegistry $fieldTypeRegistry
76 ) {
77 $this->contentGateway = $contentGateway;
78 $this->mapper = $mapper;
79 $this->storageHandler = $storageHandler;
80 $this->languageHandler = $languageHandler;
81 $this->fieldTypeRegistry = $fieldTypeRegistry;
82 }
83
90 public function createNewFields(Content $content, Type $contentType)
91 {
92 $fieldsToCopy = [];
93 $languageCodes = [];
94 $fields = $this->getFieldMap($content->fields, $languageCodes);
95 $languageCodes[$content->versionInfo->contentInfo->mainLanguageCode] = true;
96
97 foreach ($contentType->fieldDefinitions as $fieldDefinition) {
98 foreach (array_keys($languageCodes) as $languageCode) {
99 // Create fields passed from struct
100 if (isset($fields[$fieldDefinition->id][$languageCode])) {
101 $field = $fields[$fieldDefinition->id][$languageCode];
102 $this->createNewField($field, $content);
103 } elseif (
104 !$fieldDefinition->isTranslatable
105 && isset($fields[$fieldDefinition->id][$content->versionInfo->contentInfo->mainLanguageCode])
106 ) {
107 // Copy only for untranslatable field and when field in main language exists
108 // Only register here, process later as field copied should be already stored
109 $fieldsToCopy[$fieldDefinition->id][$languageCode] =
110 $fields[$fieldDefinition->id][$content->versionInfo->contentInfo->mainLanguageCode];
111 } else { // In all other cases create empty field
112 $field = $this->getEmptyField($fieldDefinition, $languageCode);
113 $content->fields[] = $field;
114 $this->createNewField($field, $content);
115 }
116 }
117 }
118
119 $this->copyFields($fieldsToCopy, $content);
120 }
121
132 protected function getEmptyField(FieldDefinition $fieldDefinition, $languageCode)
133 {
134 $fieldType = $this->fieldTypeRegistry->getFieldType($fieldDefinition->fieldType);
135
136 return new Field(
137 [
138 'fieldDefinitionId' => $fieldDefinition->id,
139 'type' => $fieldDefinition->fieldType,
140 'value' => $fieldType->getEmptyValue(),
141 'languageCode' => $languageCode,
142 ]
143 );
144 }
145
151 public function createExistingFieldsInNewVersion(Content $content)
152 {
153 foreach ($content->fields as $field) {
154 $this->createExistingFieldInNewVersion($field, $content);
155 }
156 }
157
166 protected function createNewField(Field $field, Content $content)
167 {
168 $field->versionNo = $content->versionInfo->versionNo;
169
170 $field->id = $this->contentGateway->insertNewField(
171 $content,
172 $field,
173 $this->mapper->convertToStorageValue($field)
174 );
175
176 // If the storage handler returns true, it means that $field value has been modified
177 // So we need to update it in order to store those modifications
178 // Field converter is called once again via the Mapper
179 if ($this->storageHandler->storeFieldData($content->versionInfo, $field) === true) {
180 $this->contentGateway->updateField(
181 $field,
182 $this->mapper->convertToStorageValue($field)
183 );
184 }
185 }
186
191 protected function copyFields(array $fields, Content $content)
192 {
193 foreach ($fields as $languageFields) {
194 foreach ($languageFields as $languageCode => $field) {
195 $this->copyField($field, $languageCode, $content);
196 }
197 }
198 }
199
209 protected function copyField(Field $originalField, $languageCode, Content $content)
210 {
211 $originalField->versionNo = $content->versionInfo->versionNo;
212 $field = clone $originalField;
213 $field->languageCode = $languageCode;
214
215 $field->id = $this->contentGateway->insertNewField(
216 $content,
217 $field,
218 $this->mapper->convertToStorageValue($field)
219 );
220
221 // If the storage handler returns true, it means that $field value has been modified
222 // So we need to update it in order to store those modifications
223 // Field converter is called once again via the Mapper
224 if ($this->storageHandler->copyFieldData($content->versionInfo, $field, $originalField) === true) {
225 $this->contentGateway->updateField(
226 $field,
227 $this->mapper->convertToStorageValue($field)
228 );
229 }
230
231 $content->fields[] = $field;
232 }
233
242 protected function updateField(Field $field, Content $content)
243 {
244 $this->contentGateway->updateField(
245 $field,
246 $this->mapper->convertToStorageValue($field)
247 );
248
249 // If the storage handler returns true, it means that $field value has been modified
250 // So we need to update it in order to store those modifications
251 // Field converter is called once again via the Mapper
252 if ($this->storageHandler->storeFieldData($content->versionInfo, $field) === true) {
253 $this->contentGateway->updateField(
254 $field,
255 $this->mapper->convertToStorageValue($field)
256 );
257 }
258 }
259
273 protected function createExistingFieldInNewVersion(Field $field, Content $content)
274 {
275 $originalField = clone $field;
276 $field->versionNo = $content->versionInfo->versionNo;
277
278 $this->contentGateway->insertExistingField(
279 $content,
280 $field,
281 $this->mapper->convertToStorageValue($field)
282 );
283
284 // If the storage handler returns true, it means that $field value has been modified
285 // So we need to update it in order to store those modifications
286 // Field converter is called once again via the Mapper
287 if ($this->storageHandler->copyFieldData($content->versionInfo, $field, $originalField) === true) {
288 $this->contentGateway->updateField(
289 $field,
290 $this->mapper->convertToStorageValue($field)
291 );
292 }
293 }
294
300 public function loadExternalFieldData(Content $content)
301 {
302 foreach ($content->fields as $field) {
303 $this->storageHandler->getFieldData($content->versionInfo, $field);
304 }
305 }
306
314 public function updateFields(Content $content, UpdateStruct $updateStruct, Type $contentType)
315 {
316 $updatedFields = [];
317 $fieldsToCopy = [];
318 $nonTranslatableCopiesUpdateSet = [];
319 $mainLanguageCode = $content->versionInfo->contentInfo->mainLanguageCode;
320 $languageCodes = $existingLanguageCodes = array_fill_keys($content->versionInfo->languageCodes, true);
321 $contentFieldMap = $this->getFieldMap($content->fields);
322 $updateFieldMap = $this->getFieldMap($updateStruct->fields, $languageCodes);
323 $initialLanguageCode = $this->languageHandler->load($updateStruct->initialLanguageId)->languageCode;
324 $languageCodes[$initialLanguageCode] = true;
325
326 foreach ($contentType->fieldDefinitions as $fieldDefinition) {
327 foreach (array_keys($languageCodes) as $languageCode) {
328 if (isset($updateFieldMap[$fieldDefinition->id][$languageCode])) {
329 $field = clone $updateFieldMap[$fieldDefinition->id][$languageCode];
330 $field->versionNo = $content->versionInfo->versionNo;
331 if (isset($field->id) && array_key_exists($field->languageCode, $existingLanguageCodes)) {
332 $this->updateField($field, $content);
333 $updatedFields[$fieldDefinition->id][$languageCode] = $field;
334 } else {
335 $this->createNewField($field, $content);
336 }
337 } elseif (!isset($existingLanguageCodes[$languageCode])) {
338 // If field is not set for new language
339 if ($fieldDefinition->isTranslatable) {
340 // Use empty value for translatable field
341 $field = $this->getEmptyField($fieldDefinition, $languageCode);
342 $this->createNewField($field, $content);
343 } else {
344 // Use value from main language code for untranslatable field
345 $fieldsToCopy[$fieldDefinition->id][$languageCode] =
346 isset($updateFieldMap[$fieldDefinition->id][$mainLanguageCode])
347 ? $updateFieldMap[$fieldDefinition->id][$mainLanguageCode]
348 : $contentFieldMap[$fieldDefinition->id][$mainLanguageCode];
349 }
350 } elseif (!$fieldDefinition->isTranslatable
351 && isset($updateFieldMap[$fieldDefinition->id][$mainLanguageCode])
352 ) {
353 // If field is not set for existing language and is untranslatable and main language is updated,
354 // also update copied field data
355 // Register for processing after all given fields are updated
356 $nonTranslatableCopiesUpdateSet[$fieldDefinition->id][] = $languageCode;
357 }
358
359 // If no above conditions were met - do nothing
360 }
361 }
362
363 foreach ($nonTranslatableCopiesUpdateSet as $fieldDefinitionId => $languageCodes) {
364 foreach ($languageCodes as $languageCode) {
365 $this->updateCopiedField(
366 $contentFieldMap[$fieldDefinitionId][$languageCode],
367 $updateFieldMap[$fieldDefinitionId][$mainLanguageCode],
368 $updatedFields[$fieldDefinitionId][$mainLanguageCode],
369 $content
370 );
371 }
372 }
373
374 $this->copyFields($fieldsToCopy, $content);
375 }
376
389 protected function updateCopiedField(Field $field, Field $updateField, Field $originalField, Content $content)
390 {
391 $field->versionNo = $content->versionInfo->versionNo;
392 $field->value = clone $updateField->value;
393
394 $this->contentGateway->updateField(
395 $field,
396 $this->mapper->convertToStorageValue($field)
397 );
398
399 // If the storage handler returns true, it means that $field value has been modified
400 // So we need to update it in order to store those modifications
401 // Field converter is called once again via the Mapper
402 if ($this->storageHandler->copyFieldData($content->versionInfo, $field, $originalField) === true) {
403 $this->contentGateway->updateField(
404 $field,
405 $this->mapper->convertToStorageValue($field)
406 );
407 }
408 }
409
418 protected function getFieldMap(array $fields, &$languageCodes = null)
419 {
420 $fieldMap = [];
421 foreach ($fields as $field) {
422 if (isset($languageCodes)) {
423 $languageCodes[$field->languageCode] = true;
424 }
425 $fieldMap[$field->fieldDefinitionId][$field->languageCode] = $field;
426 }
427
428 return $fieldMap;
429 }
430
437 public function deleteFields($contentId, VersionInfo $versionInfo)
438 {
439 foreach ($this->contentGateway->getFieldIdsByType($contentId, $versionInfo->versionNo) as $fieldType => $ids) {
440 $this->storageHandler->deleteFieldData($fieldType, $versionInfo, $ids);
441 }
442 $this->contentGateway->deleteFields($contentId, $versionInfo->versionNo);
443 }
444
452 public function deleteTranslationFromContentFields($contentId, array $versions, $languageCode)
453 {
454 foreach ($versions as $versionInfo) {
455 // FT-specific implementations require VersionInfo to delete data
456 $fieldTypeIdsMap = $this->contentGateway->getFieldIdsByType(
457 $versionInfo->contentInfo->id,
458 $versionInfo->versionNo,
459 $languageCode
460 );
461
462 foreach ($fieldTypeIdsMap as $fieldType => $ids) {
463 $this->storageHandler->deleteFieldData($fieldType, $versionInfo, $ids);
464 }
465 }
466
467 $this->contentGateway->deleteTranslatedFields($languageCode, $contentId);
468 }
469
476 public function deleteTranslationFromVersionFields(VersionInfo $versionInfo, $languageCode)
477 {
478 $fieldTypeIdsMap = $this->contentGateway->getFieldIdsByType(
479 $versionInfo->contentInfo->id,
480 $versionInfo->versionNo,
481 $languageCode
482 );
483 foreach ($fieldTypeIdsMap as $fieldType => $ids) {
484 $this->storageHandler->deleteFieldData($fieldType, $versionInfo, $ids);
485 }
486 $this->contentGateway->deleteTranslatedFields(
487 $languageCode,
488 $versionInfo->contentInfo->id,
489 $versionInfo->versionNo
490 );
491 }
492 }
eZ\Publish\Core\Persistence\FieldTypeRegistry
Registry for field types available to storage engines.
Definition: Persistence/FieldTypeRegistry.php:17
eZ\Publish\Core\Persistence\Legacy\Content\FieldHandler
Field Handler.
Definition: FieldHandler.php:22
eZ\Publish\Core\Persistence\Legacy\Content\FieldHandler\$fieldTypeRegistry
$fieldTypeRegistry
Definition: FieldHandler.php:52
eZ\Publish\Core\Persistence\Legacy\Content\FieldHandler\createExistingFieldInNewVersion
createExistingFieldInNewVersion(Field $field, Content $content)
Creates an existing field in a new version, no new ID is generated.
Definition: FieldHandler.php:273
eZ\Publish\Core\Persistence\Legacy\Content\FieldHandler\deleteTranslationFromContentFields
deleteTranslationFromContentFields($contentId, array $versions, $languageCode)
Deletes translated fields and their external storage data for the given Content Versions.
Definition: FieldHandler.php:452
eZ\Publish\Core\Persistence\Legacy\Content\FieldHandler\__construct
__construct(Gateway $contentGateway, Mapper $mapper, StorageHandler $storageHandler, LanguageHandler $languageHandler, FieldTypeRegistry $fieldTypeRegistry)
Creates a new Field Handler.
Definition: FieldHandler.php:70
eZ\Publish\Core\Persistence\Legacy\Content\FieldHandler\createExistingFieldsInNewVersion
createExistingFieldsInNewVersion(Content $content)
Creates existing fields in a new version for $content.
Definition: FieldHandler.php:151
eZ\Publish\Core\Persistence\Legacy\Content\FieldHandler\loadExternalFieldData
loadExternalFieldData(Content $content)
Performs external loads for the fields in $content.
Definition: FieldHandler.php:300
eZ\Publish\Core\Persistence\Legacy\Content\FieldHandler\createNewField
createNewField(Field $field, Content $content)
Creates a new field in the database.
Definition: FieldHandler.php:166
eZ\Publish\Core\Persistence\Legacy\Content\FieldHandler\deleteTranslationFromVersionFields
deleteTranslationFromVersionFields(VersionInfo $versionInfo, $languageCode)
Deletes translated fields and their external storage data for the given $versionInfo.
Definition: FieldHandler.php:476
eZ\Publish\Core\Persistence\Legacy\Content\FieldHandler\updateCopiedField
updateCopiedField(Field $field, Field $updateField, Field $originalField, Content $content)
Updates a language copy of a non-translatable field.
Definition: FieldHandler.php:389
eZ\Publish\Core\Persistence\Legacy\Content\FieldHandler\updateFields
updateFields(Content $content, UpdateStruct $updateStruct, Type $contentType)
Updates the fields in for content identified by $contentId and $versionNo in the database in respect ...
Definition: FieldHandler.php:314
eZ\Publish\Core\Persistence\Legacy\Content\FieldHandler\copyField
copyField(Field $originalField, $languageCode, Content $content)
Copies existing field to new field for given $languageCode.
Definition: FieldHandler.php:209
eZ\Publish\Core\Persistence\Legacy\Content\FieldHandler\copyFields
copyFields(array $fields, Content $content)
Definition: FieldHandler.php:191
eZ\Publish\Core\Persistence\Legacy\Content\FieldHandler\$fieldTypes
$fieldTypes
Definition: FieldHandler.php:59
eZ\Publish\Core\Persistence\Legacy\Content\FieldHandler\getFieldMap
getFieldMap(array $fields, &$languageCodes=null)
Returns given $fields structured in hash array with field definition ids and language codes as keys.
Definition: FieldHandler.php:418
eZ\Publish\Core\Persistence\Legacy\Content\FieldHandler\$storageHandler
$storageHandler
Definition: FieldHandler.php:45
eZ\Publish\Core\Persistence\Legacy\Content\FieldHandler\$mapper
$mapper
Definition: FieldHandler.php:38
eZ\Publish\Core\Persistence\Legacy\Content\FieldHandler\createNewFields
createNewFields(Content $content, Type $contentType)
Creates new fields in the database from $content of $contentType.
Definition: FieldHandler.php:90
eZ\Publish\Core\Persistence\Legacy\Content\FieldHandler\$contentGateway
$contentGateway
Definition: FieldHandler.php:28
eZ\Publish\Core\Persistence\Legacy\Content\FieldHandler\updateField
updateField(Field $field, Content $content)
Updates an existing field in the database.
Definition: FieldHandler.php:242
eZ\Publish\Core\Persistence\Legacy\Content\FieldHandler\deleteFields
deleteFields($contentId, VersionInfo $versionInfo)
Deletes the fields for $contentId in $versionInfo from the database.
Definition: FieldHandler.php:437
eZ\Publish\Core\Persistence\Legacy\Content\FieldHandler\getEmptyField
getEmptyField(FieldDefinition $fieldDefinition, $languageCode)
Returns empty Field object for given field definition and language code.
Definition: FieldHandler.php:132
eZ\Publish\Core\Persistence\Legacy\Content\FieldHandler\$languageHandler
$languageHandler
Definition: FieldHandler.php:31
eZ\Publish\Core\Persistence\Legacy\Content\Gateway
Base class for content gateways.
Definition: Persistence/Legacy/Content/Gateway.php:21
eZ\Publish\Core\Persistence\Legacy\Content\Mapper
Mapper for Content Handler.
Definition: Publish/Core/Persistence/Legacy/Content/Mapper.php:27
eZ\Publish\Core\Persistence\Legacy\Content\StorageHandler
Handler for external storages.
Definition: StorageHandler.php:16
eZ\Publish\SPI\Persistence\Content\Field
Definition: SPI/Persistence/Content/Field.php:12
eZ\Publish\SPI\Persistence\Content\Location\UpdateStruct
Definition: Content/Location/UpdateStruct.php:12
eZ\Publish\SPI\Persistence\Content\Type\FieldDefinition
Definition: SPI/Persistence/Content/Type/FieldDefinition.php:18
eZ\Publish\SPI\Persistence\Content\Type
SPI Persistence Content\Type value object.
Definition: SPI/Persistence/Content/Type.php:15
eZ\Publish\SPI\Persistence\Content\UpdateStruct
Definition: Content/UpdateStruct.php:12
eZ\Publish\SPI\Persistence\Content\VersionInfo
This class holds version information data.
Definition: SPI/Persistence/Content/VersionInfo.php:15
eZ\Publish\SPI\Persistence\Content
Content value object, bound to a version.
Definition: Publish/SPI/Persistence/Content.php:17
eZ\Publish\SPI\Persistence\Content\Language\Handler
Language Handler interface.
Definition: SPI/Persistence/Content/Language/Handler.php:15
eZ\Publish\Core\Persistence\Legacy\Content
Definition: FieldHandler.php:7
eZ\Publish\SPI\Persistence\Content\Type
Definition: SPI/Persistence/Content/Type/CreateStruct.php:7
eZ\Publish\SPI\Persistence\Content
Definition: SPI/Persistence/Content/ContentInfo.php:7
Copyright © 1998 – 2026 7x. All rights reserved. Licensed under the GNU GPLv2+.