/** * 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); }