eZ\Publish\Core\Repository\Helper\RelationProcessor::processFieldRelations PHP Метод

processFieldRelations() публичный Метод

This method creates new relations and deletes removed relations.
public processFieldRelations ( array $inputRelations, mixed $sourceContentId, mixed $sourceContentVersionNo, eZ\Publish\API\Repository\Values\ContentType\ContentType $contentType, array $existingRelations = [] )
$inputRelations array
$sourceContentId mixed
$sourceContentVersionNo mixed
$contentType eZ\Publish\API\Repository\Values\ContentType\ContentType
$existingRelations array An array of existing relations for Content version (empty when creating new content)
    public function processFieldRelations(array $inputRelations, $sourceContentId, $sourceContentVersionNo, ContentType $contentType, array $existingRelations = array())
    {
        // Map existing relations for easier handling
        $mappedRelations = array();
        foreach ($existingRelations as $relation) {
            if ($relation->type === Relation::FIELD) {
                $fieldDefinitionId = $contentType->getFieldDefinition($relation->sourceFieldDefinitionIdentifier)->id;
                $mappedRelations[$relation->type][$fieldDefinitionId][$relation->destinationContentInfo->id] = $relation;
            }
            // Using bitwise AND as Legacy Stack stores COMMON, LINK and EMBED relation types
            // in the same entry using bitmask
            if ($relation->type & Relation::LINK) {
                $mappedRelations[Relation::LINK][$relation->destinationContentInfo->id] = $relation;
            }
            if ($relation->type & Relation::EMBED) {
                $mappedRelations[Relation::EMBED][$relation->destinationContentInfo->id] = $relation;
            }
        }
        // Add new relations
        foreach ($inputRelations as $relationType => $relationData) {
            if ($relationType === Relation::FIELD) {
                foreach ($relationData as $fieldDefinitionId => $contentIds) {
                    foreach (array_keys($contentIds) as $destinationContentId) {
                        if (isset($mappedRelations[$relationType][$fieldDefinitionId][$destinationContentId])) {
                            unset($mappedRelations[$relationType][$fieldDefinitionId][$destinationContentId]);
                        } else {
                            $this->persistenceHandler->contentHandler()->addRelation(new SPIRelationCreateStruct(array('sourceContentId' => $sourceContentId, 'sourceContentVersionNo' => $sourceContentVersionNo, 'sourceFieldDefinitionId' => $fieldDefinitionId, 'destinationContentId' => $destinationContentId, 'type' => $relationType)));
                        }
                    }
                }
            } elseif ($relationType === Relation::LINK || $relationType === Relation::EMBED) {
                foreach (array_keys($relationData) as $destinationContentId) {
                    if (isset($mappedRelations[$relationType][$destinationContentId])) {
                        unset($mappedRelations[$relationType][$destinationContentId]);
                    } else {
                        $this->persistenceHandler->contentHandler()->addRelation(new SPIRelationCreateStruct(array('sourceContentId' => $sourceContentId, 'sourceContentVersionNo' => $sourceContentVersionNo, 'sourceFieldDefinitionId' => null, 'destinationContentId' => $destinationContentId, 'type' => $relationType)));
                    }
                }
            }
        }
        // Remove relations not present in input set
        foreach ($mappedRelations as $relationType => $relationData) {
            foreach ($relationData as $relationEntry) {
                switch ($relationType) {
                    case Relation::FIELD:
                        foreach ($relationEntry as $relation) {
                            $this->persistenceHandler->contentHandler()->removeRelation($relation->id, $relationType);
                        }
                        break;
                    case Relation::LINK:
                    case Relation::EMBED:
                        $this->persistenceHandler->contentHandler()->removeRelation($relationEntry->id, $relationType);
                }
            }
        }
    }

Usage Example

Пример #1
0
 /**
  * Updates the fields of a draft.
  *
  * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to update this version
  * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException if the version is not a draft
  * @throws \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException if a field in the $contentUpdateStruct is not valid
  * @throws \eZ\Publish\API\Repository\Exceptions\ContentValidationException if a required field is set to an empty value
  *
  * @param \eZ\Publish\API\Repository\Values\Content\VersionInfo $versionInfo
  * @param \eZ\Publish\API\Repository\Values\Content\ContentUpdateStruct $contentUpdateStruct
  *
  * @return \eZ\Publish\API\Repository\Values\Content\Content the content draft with the updated fields
  */
 public function updateContent(APIVersionInfo $versionInfo, APIContentUpdateStruct $contentUpdateStruct)
 {
     $contentUpdateStruct = clone $contentUpdateStruct;
     /** @var $content \eZ\Publish\Core\Repository\Values\Content\Content */
     $content = $this->loadContent($versionInfo->getContentInfo()->id, null, $versionInfo->versionNo);
     if ($content->versionInfo->status !== APIVersionInfo::STATUS_DRAFT) {
         throw new BadStateException('$versionInfo', 'Version is not a draft and can not be updated');
     }
     if (!$this->repository->canUser('content', 'edit', $content)) {
         throw new UnauthorizedException('content', 'edit', array('contentId' => $content->id));
     }
     $mainLanguageCode = $content->contentInfo->mainLanguageCode;
     $languageCodes = $this->getLanguageCodesForUpdate($contentUpdateStruct, $content);
     $contentType = $this->repository->getContentTypeService()->loadContentType($content->contentInfo->contentTypeId);
     $fields = $this->mapFieldsForUpdate($contentUpdateStruct, $contentType, $mainLanguageCode);
     $fieldValues = array();
     $spiFields = array();
     $allFieldErrors = array();
     $inputRelations = array();
     $locationIdToContentIdMapping = array();
     foreach ($contentType->getFieldDefinitions() as $fieldDefinition) {
         /** @var $fieldType \eZ\Publish\SPI\FieldType\FieldType */
         $fieldType = $this->fieldTypeRegistry->getFieldType($fieldDefinition->fieldTypeIdentifier);
         foreach ($languageCodes as $languageCode) {
             $isCopied = $isEmpty = $isRetained = false;
             $isLanguageNew = !in_array($languageCode, $content->versionInfo->languageCodes);
             $valueLanguageCode = $fieldDefinition->isTranslatable ? $languageCode : $mainLanguageCode;
             $isFieldUpdated = isset($fields[$fieldDefinition->identifier][$valueLanguageCode]);
             $isProcessed = isset($fieldValues[$fieldDefinition->identifier][$valueLanguageCode]);
             if (!$isFieldUpdated && !$isLanguageNew) {
                 $isRetained = true;
                 $fieldValue = $content->getField($fieldDefinition->identifier, $valueLanguageCode)->value;
             } elseif (!$isFieldUpdated && $isLanguageNew && !$fieldDefinition->isTranslatable) {
                 $isCopied = true;
                 $fieldValue = $content->getField($fieldDefinition->identifier, $valueLanguageCode)->value;
             } elseif ($isFieldUpdated) {
                 $fieldValue = $fields[$fieldDefinition->identifier][$valueLanguageCode]->value;
             } else {
                 $fieldValue = $fieldDefinition->defaultValue;
             }
             $fieldValue = $fieldType->acceptValue($fieldValue);
             if ($fieldType->isEmptyValue($fieldValue)) {
                 $isEmpty = true;
                 if ($fieldDefinition->isRequired) {
                     throw new ContentValidationException("Value for required field definition '%identifier%' with language '%languageCode%' is empty", ['%identifier%' => $fieldDefinition->identifier, '%languageCode%' => $languageCode]);
                 }
             } else {
                 $fieldErrors = $fieldType->validate($fieldDefinition, $fieldValue);
                 if (!empty($fieldErrors)) {
                     $allFieldErrors[$fieldDefinition->id][$languageCode] = $fieldErrors;
                 }
             }
             if (!empty($allFieldErrors)) {
                 continue;
             }
             $this->relationProcessor->appendFieldRelations($inputRelations, $locationIdToContentIdMapping, $fieldType, $fieldValue, $fieldDefinition->id);
             $fieldValues[$fieldDefinition->identifier][$languageCode] = $fieldValue;
             if ($isRetained || $isCopied || $isLanguageNew && $isEmpty || $isProcessed) {
                 continue;
             }
             $spiFields[] = new SPIField(array('id' => $isLanguageNew ? null : $content->getField($fieldDefinition->identifier, $languageCode)->id, 'fieldDefinitionId' => $fieldDefinition->id, 'type' => $fieldDefinition->fieldTypeIdentifier, 'value' => $fieldType->toPersistenceValue($fieldValue), 'languageCode' => $languageCode, 'versionNo' => $versionInfo->versionNo));
         }
     }
     if (!empty($allFieldErrors)) {
         throw new ContentFieldValidationException($allFieldErrors);
     }
     $spiContentUpdateStruct = new SPIContentUpdateStruct(array('name' => $this->nameSchemaService->resolveNameSchema($content, $fieldValues, $languageCodes, $contentType), 'creatorId' => $contentUpdateStruct->creatorId ?: $this->repository->getCurrentUserReference()->getUserId(), 'fields' => $spiFields, 'modificationDate' => time(), 'initialLanguageId' => $this->persistenceHandler->contentLanguageHandler()->loadByLanguageCode($contentUpdateStruct->initialLanguageCode)->id));
     $existingRelations = $this->loadRelations($versionInfo);
     $this->repository->beginTransaction();
     try {
         $spiContent = $this->persistenceHandler->contentHandler()->updateContent($versionInfo->getContentInfo()->id, $versionInfo->versionNo, $spiContentUpdateStruct);
         $this->relationProcessor->processFieldRelations($inputRelations, $spiContent->versionInfo->contentInfo->id, $spiContent->versionInfo->versionNo, $contentType, $existingRelations);
         $this->repository->commit();
     } catch (Exception $e) {
         $this->repository->rollback();
         throw $e;
     }
     return $this->domainMapper->buildContentDomainObject($spiContent, $contentType);
 }