Created
January 15, 2013 11:27
-
-
Save pspanja/4537989 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* File containing the Content FieldHandler class | |
* | |
* @copyright Copyright (C) 1999-2012 eZ Systems AS. All rights reserved. | |
* @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License v2 | |
* @version //autogentag// | |
*/ | |
namespace eZ\Publish\Core\Persistence\Legacy\Content; | |
use eZ\Publish\SPI\Persistence\Content; | |
use eZ\Publish\SPI\Persistence\Content\Type; | |
use eZ\Publish\SPI\Persistence\Content\VersionInfo; | |
use eZ\Publish\SPI\Persistence\Content\Field; | |
use eZ\Publish\SPI\Persistence\Content\UpdateStruct; | |
use eZ\Publish\SPI\Persistence\Content\Type\FieldDefinition; | |
use eZ\Publish\Core\Base\Exceptions\NotFoundException; | |
use eZ\Publish\Core\Base\Exceptions\InvalidArgumentException; | |
/** | |
* Field Handler. | |
*/ | |
class FieldHandler | |
{ | |
/** | |
* Content Gateway | |
* | |
* @var \eZ\Publish\Core\Persistence\Legacy\Content\Gateway | |
*/ | |
protected $contentGateway; | |
/** | |
* Content Type Handler | |
* | |
* @var \eZ\Publish\Core\Persistence\Legacy\Content\Type\Handler | |
*/ | |
public $typeHandler; | |
/** | |
* @var \eZ\Publish\Core\Persistence\Legacy\Content\Language\Handler | |
*/ | |
public $languageHandler; | |
/** | |
* Content Mapper | |
* | |
* @var \eZ\Publish\Core\Persistence\Legacy\Content\Mapper | |
*/ | |
protected $mapper; | |
/** | |
* Storage Handler | |
* | |
* @var \eZ\Publish\Core\Persistence\Legacy\Content\StorageHandler | |
*/ | |
protected $storageHandler; | |
/** | |
* Hash of SPI FieldTypes or callable callbacks to generate one. | |
* | |
* @var array | |
*/ | |
protected $fieldTypes; | |
/** | |
* Creates a new Field Handler | |
* | |
* @param \eZ\Publish\Core\Persistence\Legacy\Content\Gateway $contentGateway | |
* @param \eZ\Publish\Core\Persistence\Legacy\Content\Mapper $mapper | |
* @param \eZ\Publish\Core\Persistence\Legacy\Content\StorageHandler $storageHandler | |
* @param array $fieldTypes Hash of SPI FieldTypes or callable callbacks to generate one. | |
*/ | |
public function __construct( | |
Gateway $contentGateway, | |
Mapper $mapper, | |
StorageHandler $storageHandler, | |
array $fieldTypes ) | |
{ | |
$this->contentGateway = $contentGateway; | |
$this->mapper = $mapper; | |
$this->storageHandler = $storageHandler; | |
$this->fieldTypes = $fieldTypes; | |
} | |
/** | |
* Instantiates a FieldType\Type object | |
* | |
* @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If $type not properly setup | |
* with settings injected to service | |
* | |
* @param $identifier | |
* | |
* @return \eZ\Publish\SPI\FieldType\FieldType | |
*/ | |
protected function buildFieldType( $identifier ) | |
{ | |
if ( !isset( $this->fieldTypes[$identifier] ) ) | |
{ | |
throw new NotFoundException( | |
"FieldType", | |
"Provided \$identifier is unknown: '{$identifier}', has: " . var_export( array_keys( $this->fieldTypes ), true ) | |
); | |
} | |
if ( $this->fieldTypes[$identifier] instanceof \eZ\Publish\SPI\FieldType\FieldType ) | |
{ | |
return $this->fieldTypes[$identifier]; | |
} | |
else if ( !is_callable( $this->fieldTypes[$identifier] ) ) | |
{ | |
throw new InvalidArgumentException( "\$settings[$identifier]", 'must be instance of SPI\\FieldType\\FieldType or callback to generate it' ); | |
} | |
/** @var $closure \Closure */ | |
$closure = $this->fieldTypes[$identifier]; | |
return $closure(); | |
} | |
/** | |
* Creates new fields in the database from $content | |
* | |
* @param \eZ\Publish\SPI\Persistence\Content $content | |
* | |
* @return void | |
*/ | |
public function createNewFields( Content $content ) | |
{ | |
$languageCodes = array(); | |
$fields = $this->getFieldMap( $content->fields, $languageCodes ); | |
$contentType = $this->typeHandler->load( $content->versionInfo->contentInfo->contentTypeId ); | |
foreach ( $contentType->fieldDefinitions as $fieldDefinition ) | |
{ | |
foreach ( array_keys( $languageCodes ) as $languageCode ) | |
{ | |
if ( isset( $fields[$fieldDefinition->id][$languageCode] ) ) | |
{ | |
$field = $fields[$fieldDefinition->id][$languageCode]; | |
$this->createNewField( $field, $content ); | |
} | |
else if ( $fieldDefinition->isTranslatable | |
|| !isset( $fields[$fieldDefinition->id][$content->versionInfo->contentInfo->mainLanguageCode] ) ) | |
{ | |
$field = $this->getEmptyField( $fieldDefinition, $languageCode ); | |
$this->createNewField( $field, $content ); | |
} | |
else | |
{ | |
// Use value from main language code | |
$field = clone $fields[$fieldDefinition->id][$content->versionInfo->contentInfo->mainLanguageCode]; | |
$this->copyLegacyField( $field, $languageCode, $content ); | |
} | |
} | |
} | |
} | |
/** | |
* Returns empty Field object for given field definition and language code. | |
* | |
* Uses FieldType to create empty field value. | |
* | |
* @param \eZ\Publish\SPI\Persistence\Content\Type\FieldDefinition $fieldDefinition | |
* @param string $languageCode | |
* | |
* @return \eZ\Publish\SPI\Persistence\Content\Field | |
*/ | |
protected function getEmptyField( FieldDefinition $fieldDefinition, $languageCode ) | |
{ | |
$fieldType = $this->buildFieldType( $fieldDefinition->fieldType ); | |
return new Field( | |
array( | |
"fieldDefinitionId" => $fieldDefinition->id, | |
"type" => $fieldDefinition->fieldType, | |
"value" => $fieldType->toPersistenceValue( $fieldType->getEmptyValue() ), | |
"languageCode" => $languageCode | |
) | |
); | |
} | |
/** | |
* Creates existing fields in a new version for $content | |
* | |
* @param \eZ\Publish\SPI\Persistence\Content $content | |
* | |
* @return void | |
*/ | |
public function createExistingFieldsInNewVersion( Content $content ) | |
{ | |
foreach ( $content->fields as $field ) | |
{ | |
$this->createExistingFieldInNewVersion( $field, $content ); | |
} | |
} | |
/** | |
* Creates a new field in the database | |
* | |
* Used by self::createNewFields() and self::updateFields() | |
* | |
* @param \eZ\Publish\SPI\Persistence\Content\Field $field | |
* @param \eZ\Publish\SPI\Persistence\Content $content | |
* | |
* @return void | |
*/ | |
protected function createNewField( Field $field, Content $content ) | |
{ | |
$field->versionNo = $content->versionInfo->versionNo; | |
$field->id = $this->contentGateway->insertNewField( | |
$content, | |
$field, | |
$this->mapper->convertToStorageValue( $field ) | |
); | |
// If the storage handler returns true, it means that $field value has been modified | |
// So we need to update it in order to store those modifications | |
// Field converter is called once again via the Mapper | |
if ( $this->storageHandler->storeFieldData( $content->versionInfo, $field ) === true ) | |
{ | |
$this->contentGateway->updateField( | |
$field, | |
$this->mapper->convertToStorageValue( $field ) | |
); | |
} | |
} | |
/** | |
* Copies existing field to new field for given $languageCode. | |
* | |
* @todo from here call FieldStorage::copyLegacyField() when implemented | |
* Used by self::createNewFields() and self::updateFields() | |
* | |
* @param \eZ\Publish\SPI\Persistence\Content\Field $field | |
* @param string $languageCode | |
* @param \eZ\Publish\SPI\Persistence\Content $content | |
* | |
* @return void | |
*/ | |
protected function copyLegacyField( Field $field, $languageCode, Content $content ) | |
{ | |
$field->languageCode = $languageCode; | |
$field->versionNo = $content->versionInfo->versionNo; | |
$field->id = $this->contentGateway->insertNewField( | |
$content, | |
$field, | |
$this->mapper->convertToStorageValue( $field ) | |
); | |
// If the storage handler returns true, it means that $field value has been modified | |
// So we need to update it in order to store those modifications | |
// Field converter is called once again via the Mapper | |
if ( $this->storageHandler->storeFieldData( $content->versionInfo, $field ) === true ) | |
{ | |
$this->contentGateway->updateField( | |
$field, | |
$this->mapper->convertToStorageValue( $field ) | |
); | |
} | |
} | |
/** | |
* Updates an existing field in the database. | |
* | |
* Used by self::createNewFields() and self::updateFields() | |
* | |
* @param \eZ\Publish\SPI\Persistence\Content\Field $field | |
* @param \eZ\Publish\SPI\Persistence\Content $content | |
* | |
* @return void | |
*/ | |
protected function updateField( Field $field, Content $content ) | |
{ | |
$this->contentGateway->updateField( | |
$field, | |
$this->mapper->convertToStorageValue( $field ) | |
); | |
// If the storage handler returns true, it means that $field value has been modified | |
// So we need to update it in order to store those modifications | |
// Field converter is called once again via the Mapper | |
if ( $this->storageHandler->storeFieldData( $content->versionInfo, $field ) === true ) | |
{ | |
$this->contentGateway->updateField( | |
$field, | |
$this->mapper->convertToStorageValue( $field ) | |
); | |
} | |
} | |
/** | |
* Creates an existing field in a new version, no new ID is generated | |
* | |
* @param Field $field | |
* @param Content $content | |
* | |
* @return void | |
*/ | |
public function createExistingFieldInNewVersion( Field $field, Content $content ) | |
{ | |
$field->versionNo = $content->versionInfo->versionNo; | |
$this->contentGateway->insertExistingField( | |
$content, | |
$field, | |
$this->mapper->convertToStorageValue( $field ) | |
); | |
// If the storage handler returns true, it means that $field value has been modified | |
// So we need to update it in order to store those modifications | |
// Field converter is called once again via the Mapper | |
if ( $this->storageHandler->storeFieldData( $content->versionInfo, $field ) === true ) | |
{ | |
$this->contentGateway->updateField( | |
$field, | |
$this->mapper->convertToStorageValue( $field ) | |
); | |
} | |
} | |
/** | |
* Performs external loads for the fields in $content | |
* | |
* @param Content $content | |
* | |
* @return void | |
*/ | |
public function loadExternalFieldData( Content $content ) | |
{ | |
foreach ( $content->fields as $field ) | |
{ | |
$this->storageHandler->getFieldData( $content->versionInfo, $field ); | |
} | |
} | |
/** | |
* Updates the fields in for content identified by $contentId and $versionNo in the database in respect to $updateStruct | |
* | |
* @param \eZ\Publish\SPI\Persistence\Content $content | |
* @param \eZ\Publish\SPI\Persistence\Content\UpdateStruct $updateStruct | |
* | |
* @return void | |
*/ | |
public function updateFields( Content $content, UpdateStruct $updateStruct ) | |
{ | |
$languageCodes = $existingLanguageCodes = $this->getLanguageCodes( $content->versionInfo->languageIds ); | |
$contentFieldMap = $this->getFieldMap( $content->fields ); | |
$updateFieldMap = $this->getFieldMap( $updateStruct->fields, $languageCodes ); | |
$contentType = $this->typeHandler->load( $content->versionInfo->contentInfo->contentTypeId ); | |
foreach ( $contentType->fieldDefinitions as $fieldDefinition ) | |
{ | |
foreach ( array_keys( $languageCodes ) as $languageCode ) | |
{ | |
if ( isset( $updateFieldMap[$fieldDefinition->id][$languageCode] ) ) | |
{ | |
$field = $updateFieldMap[$fieldDefinition->id][$languageCode]; | |
$field->versionNo = $content->versionInfo->versionNo; | |
if ( isset( $field->id ) ) | |
{ | |
$this->updateField( $field, $content ); | |
} | |
else | |
{ | |
$this->createNewField( $field, $content ); | |
} | |
} | |
// If field is not set for new language | |
else if ( !isset( $existingLanguageCodes[$languageCode] ) ) | |
{ | |
if ( $fieldDefinition->isTranslatable ) | |
{ | |
// Use empty value | |
$field = $this->getEmptyField( $fieldDefinition, $languageCode ); | |
$this->createNewField( $field, $content ); | |
} | |
else | |
{ | |
// Use value from main language code | |
$field = clone $contentFieldMap[$fieldDefinition->id][$content->versionInfo->contentInfo->mainLanguageCode]; | |
$this->copyLegacyField( $field, $languageCode, $content ); | |
} | |
} | |
} | |
} | |
} | |
/** | |
* For given $languageIds returns array with language codes as keys. | |
* | |
* @param array $languageIds | |
* | |
* @return array | |
*/ | |
protected function getLanguageCodes( array $languageIds ) | |
{ | |
$languageCodes = array(); | |
foreach ( $languageIds as $languageId ) | |
{ | |
$languageCodes[$this->languageHandler->load( $languageId )->languageCode] = true; | |
} | |
return $languageCodes; | |
} | |
/** | |
* Returns given $fields structured in hash array with field definition ids and language codes as keys. | |
* | |
* @param \eZ\Publish\SPI\Persistence\Content\Field[] $fields | |
* @param array $languageCodes | |
* | |
* @return \eZ\Publish\SPI\Persistence\Content\Field[][] | |
*/ | |
protected function getFieldMap( array $fields, &$languageCodes = null ) | |
{ | |
$fieldMap = array(); | |
foreach ( $fields as $field ) | |
{ | |
if ( isset( $languageCodes ) ) | |
{ | |
$languageCodes[$field->languageCode] = true; | |
} | |
$fieldMap[$field->fieldDefinitionId][$field->languageCode] = $field; | |
} | |
return $fieldMap; | |
} | |
/** | |
* Deletes the fields for $contentId in $versionInfo from the database | |
* | |
* @param int $contentId | |
* @param \eZ\Publish\SPI\Persistence\Content\VersionInfo $versionInfo | |
* | |
* @return void | |
*/ | |
public function deleteFields( $contentId, VersionInfo $versionInfo ) | |
{ | |
foreach ( $this->contentGateway->getFieldIdsByType( $contentId, $versionInfo->versionNo ) | |
as $fieldType => $ids ) | |
{ | |
$this->storageHandler->deleteFieldData( $fieldType, $versionInfo, $ids ); | |
} | |
$this->contentGateway->deleteFields( $contentId, $versionInfo->versionNo ); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment