Permalink
Switch branches/tags
Find file Copy path
6688 lines (6053 sloc) 261 KB
<?php
/**
* File containing the eZContentObject class.
*
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
* @version //autogentag//
* @package kernel
*/
/**
* Encapsulates data about and methods to work with content objects
*
* @package kernel
*/
class eZContentObject extends eZPersistentObject
{
const STATUS_DRAFT = 0;
const STATUS_PUBLISHED = 1;
const STATUS_ARCHIVED = 2;
const PACKAGE_ERROR_NO_CLASS = 1;
const PACKAGE_ERROR_EXISTS = 2;
const PACKAGE_ERROR_NODE_EXISTS = 3;
const PACKAGE_ERROR_MODIFIED = 101;
const PACKAGE_ERROR_HAS_CHILDREN = 102;
const PACKAGE_REPLACE = 1;
const PACKAGE_SKIP = 2;
const PACKAGE_NEW = 3;
const PACKAGE_UPDATE = 6;
const PACKAGE_DELETE = 4;
const PACKAGE_KEEP = 5;
const RELATION_COMMON = 1;
const RELATION_EMBED = 2;
const RELATION_LINK = 4;
const RELATION_ATTRIBUTE = 8;
/**
* Initializes the object with $row.
*
* If $row is an integer, it will try to fetch it from the database using it as the unique ID.
*
* @param int|array $row
*/
public function __construct( $row )
{
parent::__construct( $row );
$this->ClassIdentifier = false;
if ( isset( $row['contentclass_identifier'] ) )
$this->ClassIdentifier = $row['contentclass_identifier'];
if ( isset( $row['class_identifier'] ) )
$this->ClassIdentifier = $row['class_identifier'];
$this->ClassName = false;
// Depending on how the information is retrieved, the "serialized_name_list" is sometimes available in "class_serialized_name_list" key
if ( isset( $row['class_serialized_name_list'] ) )
$row['serialized_name_list'] = $row['class_serialized_name_list'];
// Depending on how the information is retrieved, the "contentclass_name" is sometimes available in "class_name" key
if ( isset( $row['class_name'] ) )
$row['contentclass_name'] = $row['class_name'];
if ( isset( $row['contentclass_name'] ) )
$this->ClassName = $row['contentclass_name'];
if ( isset( $row['serialized_name_list'] ) )
$this->ClassName = eZContentClass::nameFromSerializedString( $row['serialized_name_list'] );
$this->CurrentLanguage = false;
if ( isset( $row['content_translation'] ) )
{
$this->CurrentLanguage = $row['content_translation'];
}
else if ( isset( $row['real_translation'] ) )
{
$this->CurrentLanguage = $row['real_translation'];
}
else if ( isset( $row['language_mask'] ) )
{
$topPriorityLanguage = eZContentLanguage::topPriorityLanguageByMask( $row['language_mask'] );
if ( $topPriorityLanguage )
{
$this->CurrentLanguage = $topPriorityLanguage->attribute( 'locale' );
}
}
// Initialize the permission array cache
$this->Permissions = array();
}
static function definition()
{
static $definition = array( "fields" => array( "id" => array( 'name' => 'ID',
'datatype' => 'integer',
'default' => 0,
'required' => true ),
"section_id" => array( 'name' => "SectionID",
'datatype' => 'integer',
'default' => 0,
'required' => true,
'foreign_class' => 'eZSection',
'foreign_attribute' => 'id',
'multiplicity' => '1..*' ),
"owner_id" => array( 'name' => "OwnerID",
'datatype' => 'integer',
'default' => 0,
'required' => true,
'foreign_class' => 'eZUser',
'foreign_attribute' => 'contentobject_id',
'multiplicity' => '1..*'),
"contentclass_id" => array( 'name' => "ClassID",
'datatype' => 'integer',
'default' => 0,
'required' => true,
'foreign_class' => 'eZContentClass',
'foreign_attribute' => 'id',
'multiplicity' => '1..*' ),
"name" => array( 'name' => "Name",
'datatype' => 'string',
'default' => '',
'required' => true ),
"published" => array( 'name' => "Published",
'datatype' => 'integer',
'default' => 0,
'required' => true ),
"modified" => array( 'name' => "Modified",
'datatype' => 'integer',
'default' => 0,
'required' => true ),
"current_version" => array( 'name' => "CurrentVersion",
'datatype' => 'integer',
'default' => 0,
'required' => true ),
"status" => array( 'name' => "Status",
'datatype' => 'integer',
'default' => 0,
'required' => true ),
'remote_id' => array( 'name' => "RemoteID",
'datatype' => 'string',
'default' => '',
'required' => true ),
'language_mask' => array( 'name' => 'LanguageMask',
'datatype' => 'integer',
'default' => 0,
'required' => true ),
'initial_language_id' => array( 'name' => 'InitialLanguageID',
'datatype' => 'integer',
'default' => 0,
'required' => true,
'foreign_class' => 'eZContentLanguage',
'foreign_attribute' => 'id',
'multiplicity' => '1..*' ) ),
"keys" => array( "id" ),
"function_attributes" => array( "current" => "currentVersion",
"published_version" => "publishedVersion",
'versions' => 'versions',
'author_array' => 'authorArray',
"class_name" => "className",
"content_class" => "contentClass",
"contentobject_attributes" => "contentObjectAttributes",
"owner" => "owner",
"related_contentobject_array" => "relatedContentObjectList",
"related_contentobject_count" => "relatedContentObjectCount",
'reverse_related_contentobject_array' => 'reverseRelatedObjectList',
'reverse_related_contentobject_count' => 'reverseRelatedObjectCount',
"linked_contentobject_array" => "linkedContentObjectList",
"linked_contentobject_count" => "linkedContentObjectCount",
'reverse_linked_contentobject_array' => 'reverseLinkedObjectList',
'reverse_linked_contentobject_count' => 'reverseLinkedObjectCount',
"embedded_contentobject_array" => "embeddedContentObjectList",
"embedded_contentobject_count" => "embeddedContentObjectCount",
'reverse_embedded_contentobject_array' => 'reverseEmbeddedObjectList',
'reverse_embedded_contentobject_count' => 'reverseEmbeddedObjectCount',
"can_read" => "canRead",
"can_pdf" => "canPdf",
"can_diff" => "canDiff",
"can_create" => "canCreate",
"can_create_class_list" => "canCreateClassList",
"can_edit" => "canEdit",
"can_translate" => "canTranslate",
"can_remove" => "canRemove",
"can_move" => "canMoveFrom",
"can_move_from" => "canMoveFrom",
'can_view_embed' => 'canViewEmbed',
"data_map" => "dataMap",
"grouped_data_map" => "groupedDataMap",
"main_parent_node_id" => "mainParentNodeID",
"assigned_nodes" => "assignedNodes",
"visible_nodes" => "visibleNodes",
"has_visible_node" => "hasVisibleNode",
"parent_nodes" => "parentNodeIDArray",
"main_node_id" => "mainNodeID",
"main_node" => "mainNode",
"default_language" => "defaultLanguage",
"content_action_list" => "contentActionList",
"class_identifier" => "contentClassIdentifier",
'class_group_id_list' => 'contentClassGroupIDList',
'name' => 'name',
'match_ingroup_id_list' => 'matchIngroupIDList',
'remote_id' => 'remoteID',
'current_language' => 'currentLanguage',
'current_language_object' => 'currentLanguageObject',
'initial_language' => 'initialLanguage',
'initial_language_code' => 'initialLanguageCode',
'available_languages' => 'availableLanguages',
'language_codes' => 'availableLanguages',
'language_js_array' => 'availableLanguagesJsArray',
'languages' => 'languages',
'all_languages' => 'allLanguages',
'can_edit_languages' => 'canEditLanguages',
'can_create_languages' => 'canCreateLanguages',
'always_available' => 'isAlwaysAvailable',
'allowed_assign_section_list' => 'allowedAssignSectionList',
'allowed_assign_state_id_list' => 'allowedAssignStateIDList',
'allowed_assign_state_list' => 'allowedAssignStateList',
'state_id_array' => 'stateIDArray',
'state_identifier_array' => 'stateIdentifierArray',
'section_identifier' => 'sectionIdentifier' ),
"increment_key" => "id",
"class_name" => "eZContentObject",
"sort" => array( "id" => "asc" ),
"name" => "ezcontentobject" );
return $definition;
}
/**
* Get class groups this object's class belongs to if match for class groups is enabled, otherwise false
*
* @return array|bool
*/
function matchIngroupIDList()
{
$contentINI = eZINI::instance( 'content.ini' );
$inList = false;
if( $contentINI->variable( 'ContentOverrideSettings', 'EnableClassGroupOverride' ) == 'true' )
{
$contentClass = $this->contentClass();
$inList = $contentClass->attribute( 'ingroup_id_list' );
}
return $inList;
}
/**
* Stores the object
*
* Transaction unsafe. If you call several transaction unsafe methods you must enclose
* the calls within a db transaction; thus within db->begin and db->commit.
*
* @param array $fieldFilters
*/
function store( $fieldFilters = null )
{
// Unset the cache
global $eZContentObjectContentObjectCache;
unset( $eZContentObjectContentObjectCache[$this->ID] );
global $eZContentObjectDataMapCache;
unset( $eZContentObjectDataMapCache[$this->ID] );
global $eZContentObjectVersionCache;
unset( $eZContentObjectVersionCache[$this->ID] );
$db = eZDB::instance();
$db->begin();
$this->storeNodeModified();
parent::store( $fieldFilters );
$db->commit();
}
/**
* Clear in-memory caches.
*
* If $idArray is ommitted, the caches are cleared for all objects.
*
* @param array $idArray Objects to clear caches for.
*/
static function clearCache( $idArray = array() )
{
if ( is_numeric( $idArray ) )
$idArray = array( $idArray );
// clear in-memory cache for all objects
if ( count( $idArray ) == 0 )
{
unset( $GLOBALS['eZContentObjectContentObjectCache'] );
unset( $GLOBALS['eZContentObjectDataMapCache'] );
unset( $GLOBALS['eZContentObjectVersionCache'] );
return;
}
// clear in-memory cache for specified object(s)
global $eZContentObjectContentObjectCache;
global $eZContentObjectDataMapCache;
global $eZContentObjectVersionCache;
foreach ( $idArray as $objectID )
{
unset( $eZContentObjectContentObjectCache[$objectID] );
unset( $eZContentObjectDataMapCache[$objectID] );
unset( $eZContentObjectVersionCache[$objectID] );
}
}
/**
* Update all nodes to set modified_subnode value
*
* Transaction unsafe. If you call several transaction unsafe methods you must enclose
* the calls within a db transaction; thus within db->begin and db->commit.
*/
function storeNodeModified()
{
if ( is_numeric( $this->ID ) )
{
$nodeArray = $this->assignedNodes();
$db = eZDB::instance();
$db->begin();
foreach ( array_keys( $nodeArray ) as $key )
{
$nodeArray[$key]->updateAndStoreModified();
}
$db->commit();
}
}
/**
* Returns an object's name for the version given by $version in the language given by $lang
*
* @param int|bool $version If omitted, the current version will be used
* @param bool $lang If omitted, the initial object language will be used
* @return bool|string
*/
function name( $version = false , $lang = false )
{
// if the object id is null, we can't read data from the database
// and return the locally known name
if ( $this->attribute( 'id' ) === null )
{
return $this->Name;
}
if ( !$version )
{
$version = $this->attribute( 'current_version' );
}
if ( !$lang && $this->CurrentLanguage )
{
$lang = $this->CurrentLanguage;
}
return $this->versionLanguageName( $version, $lang );
}
/**
* Returns all translations of the current object's name
*
* @return string[]
*/
function names()
{
$version = $this->attribute( 'current_version' );
$id = $this->attribute( 'id' );
$db = eZDB::instance();
$rows = $db->arrayQuery( "SELECT name, real_translation FROM ezcontentobject_name WHERE contentobject_id = '$id' AND content_version='$version'" );
$names = array();
foreach ( $rows as $row )
{
$names[$row['real_translation']] = $row['name'];
}
return $names;
}
/**
* Returns the object name for version $version in the language $lang
*
* @param int $version
* @param string|bool $lang If omitted, the initial language of the object is used
* @return string|bool
*/
function versionLanguageName( $version, $lang = false )
{
$name = false;
if ( !$version > 0 )
{
eZDebug::writeNotice( "There is no object name for version($version) of the content object ($contentObjectID) in language($lang)", __METHOD__ );
return $name;
}
$db = eZDB::instance();
$contentObjectID = $this->attribute( 'id' );
if ( !$lang )
{
// If $lang not given we will use the initial language of the object
$query = "SELECT initial_language_id FROM ezcontentobject WHERE id='$contentObjectID'";
$rows = $db->arrayQuery( $query );
if ( $rows )
{
$languageID = $rows[0]['initial_language_id'];
$language = eZContentLanguage::fetch( $languageID );
if ( $language )
{
$lang = $language->attribute( 'locale' );
}
else
{
return $name;
}
}
else
{
return $name;
}
}
$lang = $db->escapeString( $lang );
$version = (int) $version;
$languageID = $this->attribute( 'initial_language_id' );
if ( $this->attribute( 'always_available' ) )
{
$languageID = (int) $languageID | 1;
}
$query= "SELECT name, content_translation
FROM ezcontentobject_name
WHERE contentobject_id = '$contentObjectID'
AND content_version = '$version'
AND ( content_translation = '$lang' OR language_id = '$languageID' )";
$result = $db->arrayQuery( $query );
$resCount = count( $result );
if( $resCount < 1 )
{
eZDebug::writeNotice( "There is no object name for version($version) of the content object ($contentObjectID) in language($lang)", __METHOD__ );
}
else if( $resCount > 1 )
{
// we have name in requested language => find and return it
foreach( $result as $row )
{
if( $row['content_translation'] == $lang )
{
$name = $row['name'];
break;
}
}
}
else
{
// we don't have name in requested language(or requested language is the same as initial language) => use name in initial language
$name = $result[0]['name'];
}
return $name;
}
/**
* Sets the name of the object, in memory only. Use {@see setName()} to change it permanently
*
* @param string $name
*/
function setCachedName( $name )
{
$this->Name = $name;
}
/**
* Sets the name of the object in all translations.
*
* Transaction unsafe. If you call several transaction unsafe methods you must enclose
* the calls within a db transaction; thus within db->begin and db->commit.
*
* @param string $objectName
* @param int|bool $versionNum
* @param int|bool $languageCode
*/
function setName( $objectName, $versionNum = false, $languageCode = false )
{
$initialLanguageCode = false;
if ( $initialLanguage = $this->initialLanguage() )
{
$initialLanguageCode = $initialLanguage->attribute( 'locale' );
}
$db = eZDB::instance();
if ( $languageCode == false )
{
$languageCode = $initialLanguageCode;
}
$languageCode = $db->escapeString( $languageCode );
if ( $languageCode == $initialLanguageCode )
{
$this->Name = $objectName;
}
if ( !$versionNum )
{
$versionNum = $this->attribute( 'current_version' );
}
$objectID =(int) $this->attribute( 'id' );
$versionNum =(int) $versionNum;
$languageID =(int) eZContentLanguage::idByLocale( $languageCode );
$objectName = $db->escapeString( $objectName );
$db->begin();
// Check if name is already set before setting/changing it.
// This helps to avoid deadlocks in mysql: a pair of DELETE/INSERT might cause deadlock here
// in case of concurrent execution.
$rows = $db->arrayQuery( "SELECT COUNT(*) AS count FROM ezcontentobject_name WHERE contentobject_id = '$objectID'
AND content_version = '$versionNum' AND content_translation ='$languageCode'" );
if ( $rows[0]['count'] )
{
$db->query( "UPDATE ezcontentobject_name SET name='$objectName'
WHERE
contentobject_id = '$objectID' AND
content_version = '$versionNum' AND
content_translation ='$languageCode'" );
}
else
{
$db->query( "INSERT INTO ezcontentobject_name( contentobject_id,
name,
content_version,
content_translation,
real_translation,
language_id )
VALUES( '$objectID',
'$objectName',
'$versionNum',
'$languageCode',
'$languageCode',
'$languageID' )" );
}
$db->commit();
}
/**
* Return a map with all the content object attributes where the keys are the attribute identifiers.
*
* @return eZContentObjectAttribute[]
*/
function dataMap()
{
return $this->fetchDataMap();
}
/**
* Generates a map with all the content object attributes where the keys are
* the attribute identifiers grouped by class attribute category.
*
* Result is not cached, so make sure you don't call this over and over.
*
* @return array
*/
public function groupedDataMap()
{
return self::createGroupedDataMap( $this->fetchDataMap() );
}
/**
* Generates a map with all the content object attributes where the keys are
* the attribute identifiers grouped by class attribute category.
*
* Result is not cached, so make sure you don't call this over and over.
*
* @param eZContentObjectAttribute[] $contentObjectAttributes Array of eZContentObjectAttribute objects
* @return array
*/
public static function createGroupedDataMap( $contentObjectAttributes )
{
$groupedDataMap = array();
$contentINI = eZINI::instance( 'content.ini' );
$categorys = $contentINI->variable( 'ClassAttributeSettings', 'CategoryList' );
$defaultCategory = $contentINI->variable( 'ClassAttributeSettings', 'DefaultCategory' );
foreach( $contentObjectAttributes as $attribute )
{
$classAttribute = $attribute->contentClassAttribute();
$attributeCategory = $classAttribute->attribute('category');
$attributeIdentifier = $classAttribute->attribute( 'identifier' );
if ( !isset( $categorys[ $attributeCategory ] ) || !$attributeCategory )
$attributeCategory = $defaultCategory;
if ( !isset( $groupedDataMap[ $attributeCategory ] ) )
$groupedDataMap[ $attributeCategory ] = array();
$groupedDataMap[ $attributeCategory ][$attributeIdentifier] = $attribute;
}
return $groupedDataMap;
}
/**
* Returns a map with all the content object attributes where the keys are the attribute identifiers.
*
* @param int|bool $version
* @param string|bool $language
* @return eZContentObjectAttribute[]
*/
function fetchDataMap( $version = false, $language = false )
{
// Global variable to cache datamaps
global $eZContentObjectDataMapCache;
if ( $version == false )
$version = $this->attribute( 'current_version' );
if ( $language == false )
{
$language = $this->CurrentLanguage;
}
if ( !$language || !isset( $eZContentObjectDataMapCache[$this->ID][$version][$language] ) )
{
$data = $this->contentObjectAttributes( true, $version, $language );
if ( !$language )
{
$language = $this->CurrentLanguage;
}
// Store the attributes for later use
$this->ContentObjectAttributeArray[$version][$language] = $data;
$eZContentObjectDataMapCache[$this->ID][$version][$language] = $data;
}
else
{
$data = $eZContentObjectDataMapCache[$this->ID][$version][$language];
}
if ( !isset( $this->DataMap[$version][$language] ) )
{
$ret = array();
/* @var eZContentObjectAttribute[] $data */
foreach( $data as $key => $item )
{
$identifier = $item->contentClassAttributeIdentifier();
$ret[$identifier] = $data[$key];
}
$this->DataMap[$version][$language] = $ret;
}
else
{
$ret = $this->DataMap[$version][$language];
}
return $ret;
}
/**
* Resets (empties) the current object's data map
*
* @return array
*/
function resetDataMap()
{
$this->ContentObjectAttributeArray = array();
$this->ContentObjectAttributes = array();
$this->DataMap = array();
return $this->DataMap;
}
/**
* Fetches a set of content object attributes by their class identifiers.
*
* @param string[] $identifierArray
* @param int|bool $version
* @param string[]|bool $languageArray
* @param bool $asObject If true, returns an array of eZContentObjectAttributes, a normal array otherwise
*
* @return eZContentObjectAttribute[]|array|null
*/
function fetchAttributesByIdentifier( $identifierArray, $version = false, $languageArray = false, $asObject = true )
{
if ( count( $identifierArray ) === 0 )
{
return null;
}
$db = eZDB::instance();
$identifierQuotedString = array();
foreach ( $identifierArray as $identifier )
{
$identifierQuotedString[] = "'$identifier'";
}
if ( !$version or !is_numeric( $version ) )
{
$version = $this->CurrentVersion;
}
if ( is_array( $languageArray ) )
{
$langCodeQuotedString = array();
foreach ( $languageArray as $langCode )
{
if ( is_string( $langCode ) )
$langCodeQuotedString[] = "'$langCode'";
}
if ( !empty( $langCodeQuotedString ) )
{
$languageText = "AND ";
$languageText .= $db->generateSQLINStatement( $langCodeQuotedString, 'ezcontentobject_attribute.language_code' );
}
}
if ( !isset( $languageText ) )
{
$languageText = "AND " . eZContentLanguage::sqlFilter( 'ezcontentobject_attribute', 'ezcontentobject_version' );
}
$versionText = "AND ezcontentobject_attribute.version = '$version'";
$query = "SELECT ezcontentobject_attribute.*, ezcontentclass_attribute.identifier as identifier
FROM ezcontentobject_attribute, ezcontentclass_attribute, ezcontentobject_version
WHERE
ezcontentclass_attribute.version = ". eZContentClass::VERSION_STATUS_DEFINED . " AND
ezcontentclass_attribute.id = ezcontentobject_attribute.contentclassattribute_id AND
ezcontentobject_version.contentobject_id = {$this->ID} AND
ezcontentobject_version.version = {$version} AND
ezcontentobject_attribute.contentobject_id = {$this->ID}
{$languageText}
{$versionText}
AND
";
$query .= $db->generateSQLINStatement( $identifierQuotedString, 'identifier' );
$rows = $db->arrayQuery( $query );
if ( count( $rows ) > 0 )
{
if ( $asObject )
{
$returnArray = array();
foreach( $rows as $row )
{
$returnArray[$row['id']] = new eZContentObjectAttribute( $row );
}
return $returnArray;
}
else
{
return $rows;
}
}
return null;
}
/**
* Returns the owner of the object as a content object.
*
* @return eZContentObject|null
*/
function owner()
{
if ( $this->OwnerID != 0 )
{
return eZContentObject::fetch( $this->OwnerID );
}
return null;
}
/**
* Returns the content class group identifiers for the current content object
*
* @return array
*/
function contentClassGroupIDList()
{
$contentClass = $this->contentClass();
return $contentClass->attribute( 'ingroup_id_list' );
}
/**
* Returns the content class identifer for the current content object
*
* The object will cache the class name information so multiple calls will be fast.
*
* @return string|bool|null
*/
function contentClassIdentifier()
{
if ( !is_numeric( $this->ClassID ) )
{
$retValue = null;
return $retValue;
}
if ( $this->ClassIdentifier !== false )
return $this->ClassIdentifier;
$this->ClassIdentifier = eZContentClass::classIdentifierByID( $this->ClassID );
return $this->ClassIdentifier;
}
/**
* Returns the content class for the current content object
*
* @return eZContentClass|null
*/
function contentClass()
{
if ( !is_numeric( $this->ClassID ) )
{
$retValue = null;
return $retValue;
}
return eZContentClass::fetch( $this->ClassID );
}
/**
* Returns the remote id of the current content object
*
* @return string
*/
function remoteID()
{
$remoteID = $this->attribute( 'remote_id', true );
if ( !$remoteID )
{
$this->setAttribute( 'remote_id', eZRemoteIdUtility::generate( 'object' ) );
if ( $this->attribute( 'id' ) !== null )
$this->sync( array( 'remote_id' ) );
$remoteID = $this->attribute( 'remote_id', true );
}
return $remoteID;
}
/**
* Returns the ID of the the current object's main node
*
* @return int|null
*/
function mainParentNodeID()
{
$list = eZContentObjectTreeNode::getParentNodeIdListByContentObjectID( $this->ID, false, true );
return isset( $list[0] ) ? $list[0] : null;
}
/**
* Returns a contentobject by remote ID
*
* @param string $remoteID
* @param bool $asObject
* @return eZContentObject|array|null
*/
static function fetchByRemoteID( $remoteID, $asObject = true )
{
$db = eZDB::instance();
$remoteID =$db->escapeString( $remoteID );
$resultArray = $db->arrayQuery( 'SELECT id FROM ezcontentobject WHERE remote_id=\'' . $remoteID . '\'' );
if ( count( $resultArray ) != 1 )
$object = null;
else
$object = eZContentObject::fetch( $resultArray[0]['id'], $asObject );
return $object;
}
/**
* Fetches a content object by ID
*
* @param int $id ID of the content object to fetch
* @param bool $asObject Return the result as an object (true) or an assoc. array (false)
*
* @return eZContentObject
*/
static function fetch( $id, $asObject = true )
{
global $eZContentObjectContentObjectCache;
// If the object given by its id is not cached or should be returned as array
// then we fetch it from the DB (objects are always cached as arrays).
if ( !isset( $eZContentObjectContentObjectCache[$id] ) or $asObject === false )
{
$db = eZDB::instance();
$resArray = $db->arrayQuery( eZContentObject::createFetchSQLString( $id ) );
$objectArray = array();
if ( count( $resArray ) == 1 && $resArray !== false )
{
$objectArray = $resArray[0];
}
else
{
eZDebug::writeError( "Object not found ($id)", __METHOD__ );
$retValue = null;
return $retValue;
}
if ( $asObject )
{
$obj = new eZContentObject( $objectArray );
$eZContentObjectContentObjectCache[$id] = $obj;
}
else
{
return $objectArray;
}
return $obj;
}
else
{
return $eZContentObjectContentObjectCache[$id];
}
}
/**
* Returns true, if a content object with the ID $id exists, false otherwise
*
* @param int $id
* @return bool
*/
static function exists( $id )
{
global $eZContentObjectContentObjectCache;
// Check the global cache
if ( isset( $eZContentObjectContentObjectCache[$id] ) )
return true;
// If the object is not cached we need to check the DB
$db = eZDB::instance();
$resArray = $db->arrayQuery( eZContentObject::createFetchSQLString( $id ) );
if ( $resArray !== false and count( $resArray ) == 1 )
{
return true;
}
return false;
}
/**
* Creates the SQL for fetching the object with ID $id and returns the string.
*
* @param int $id
* @return string
*/
static function createFetchSQLString( $id )
{
$id = (int) $id;
$fetchSQLString = "SELECT ezcontentobject.*,
ezcontentclass.serialized_name_list as serialized_name_list,
ezcontentclass.identifier as contentclass_identifier,
ezcontentclass.is_container as is_container
FROM
ezcontentobject,
ezcontentclass
WHERE
ezcontentobject.id='$id' AND
ezcontentclass.id = ezcontentobject.contentclass_id AND
ezcontentclass.version=0";
return $fetchSQLString;
}
/**
* Creates the SQL for filtering objects by visibility, used by IgnoreVisibility on some fetches.
* The object is visible if 1 or more assigned nodes are visible.
*
* @since Version 4.1
* @param bool $IgnoreVisibility ignores visibility if true
* @param string $ezcontentobjectTable name of ezcontentobject table used in sql
* @return string with sql condition for node filtering by visibility
*/
static function createFilterByVisibilitySQLString( $IgnoreVisibility = false, $ezcontentobjectTable = 'ezcontentobject' )
{
if ( $IgnoreVisibility )
return '';
return " AND ( SELECT MIN( ezct.is_invisible ) FROM ezcontentobject_tree ezct WHERE ezct.contentobject_id = $ezcontentobjectTable.id ) = 0 ";
}
/**
* Fetches the contentobject which has a node with ID $nodeID
*
* $nodeID can also be an array of NodeIDs. In this case, an array of content objects will be returned
*
* @param int|array $nodeID Single nodeID or array of NodeIDs
* @param bool $asObject If results have to be returned as eZContentObject instances or not
* @return eZContentObject|eZContentObject[]|array|null Content object or array of content objects.
* Content objects can be eZContentObject instances or array result sets
*/
static function fetchByNodeID( $nodeID, $asObject = true )
{
global $eZContentObjectContentObjectCache;
$resultAsArray = is_array( $nodeID );
$nodeID = (array)$nodeID;
$db = eZDB::instance();
$resArray = $db->arrayQuery(
"SELECT co.*, con.name as name, con.real_translation, cot.node_id
FROM ezcontentobject co
JOIN ezcontentobject_tree cot ON co.id = cot.contentobject_id AND co.current_version = cot.contentobject_version
JOIN ezcontentobject_name con ON co.id = con.contentobject_id AND co.current_version = con.content_version
WHERE " .
$db->generateSQLINStatement( $nodeID, 'cot.node_id', false, true, 'int' ) . " AND " .
eZContentLanguage::sqlFilter( 'con', 'co' )
);
if ( $resArray === false || empty( $resArray ) )
{
eZDebug::writeError( 'A problem occured while fetching objects with following NodeIDs : ' . implode( ', ', $nodeID ), __METHOD__ );
return $resultAsArray ? array() : null;
}
$objectArray = array();
if ( $asObject )
{
foreach ( $resArray as $res )
{
$objectArray[$res['node_id']] = $eZContentObjectContentObjectCache[$res['id']] = new self( $res );
}
}
else
{
foreach ( $resArray as $res )
{
$objectArray[$res['node_id']] = $res;
}
}
if ( !$resultAsArray )
return $objectArray[$res['node_id']];
return $objectArray;
}
/**
* Fetches a content object list based on an array of content object ids
*
* @param array $idArray array of content object ids
* @param bool $asObject
* Wether to get the result as an array of eZContentObject or an
* array of associative arrays
* @param bool|string $lang A language code to put at the top of the prioritized
* languages list.
*
* @return array(contentObjectID => eZContentObject|array)
* array of eZContentObject (if $asObject = true) or array of
* associative arrays (if $asObject = false)
*/
static function fetchIDArray( $idArray, $asObject = true , $lang = false )
{
global $eZContentObjectContentObjectCache;
$db = eZDB::instance();
$resRowArray = $db->arrayQuery(
"SELECT ezcontentclass.serialized_name_list as class_serialized_name_list, ezcontentobject.*, ezcontentobject_name.name as name, ezcontentobject_name.real_translation
FROM
ezcontentclass,
ezcontentobject,
ezcontentobject_name
WHERE
ezcontentclass.id=ezcontentobject.contentclass_id AND " .
// All elements from $idArray should be casted to (int)
$db->generateSQLINStatement( $idArray, 'ezcontentobject.id', false, true, 'int' ) . " AND
ezcontentobject.id = ezcontentobject_name.contentobject_id AND
ezcontentobject.current_version = ezcontentobject_name.content_version AND " .
eZContentLanguage::sqlFilter( 'ezcontentobject_name', 'ezcontentobject', 'language_id', 'language_mask', $lang )
);
$objectRetArray = array();
foreach ( $resRowArray as $resRow )
{
$objectID = $resRow['id'];
$resRow['class_name'] = eZContentClass::nameFromSerializedString( $resRow['class_serialized_name_list'] );
if ( $asObject )
{
$obj = new eZContentObject( $resRow );
$obj->ClassName = $resRow['class_name'];
if ( $lang !== false )
{
$eZContentObjectContentObjectCache[$objectID] = $obj;
}
$objectRetArray[$objectID] = $obj;
}
else
{
$objectRetArray[$objectID] = $resRow;
}
}
return $objectRetArray;
}
/**
* Returns an array of content objects.
*
* @param bool $asObject Whether to return objects or not
* @param array|null $conditions Optional conditions to limit the fetch
* @param int|bool $offset Where to start fetch from, set to false to skip it.
* @param int|bool $limit Maximum number of objects to fetch, set false to skip it.
* @return eZContentObject[]|array|null
*/
static function fetchList( $asObject = true, $conditions = null, $offset = false, $limit = false )
{
$limitation = null;
if ( $offset !== false or
$limit !== false )
$limitation = array( 'offset' => $offset,
'length' => $limit );
return eZPersistentObject::fetchObjectList( eZContentObject::definition(),
null,
$conditions, null, $limitation,
$asObject );
}
/**
* Returns a filtered array of content objects.
*
* @param array|null $conditions Optional conditions to limit the fetch
* @param int|bool $offset Where to start fetch from, set to false to skip it.
* @param int|bool $limit Maximum number of objects to fetch, set false to skip it.
* @param bool $asObject Whether to return objects or not
* @return array|eZPersistentObject[]|null
*/
static function fetchFilteredList( $conditions = null, $offset = false, $limit = false, $asObject = true )
{
$limits = null;
if ( $offset or $limit )
$limits = array( 'offset' => $offset,
'length' => $limit );
return eZPersistentObject::fetchObjectList( eZContentObject::definition(),
null,
$conditions, null, $limits,
$asObject );
}
/**
* Returns the number of objects in the database. Optionally \a $conditions can be used to limit the list count.
* @param array|null $conditions
* @return int
*/
static function fetchListCount( $conditions = null )
{
$rows = eZPersistentObject::fetchObjectList( eZContentObject::definition(),
array(),
$conditions,
false/* we don't want any sorting when counting. Sorting leads to error on postgresql 8.x */,
null,
false, false,
array( array( 'operation' => 'count( * )',
'name' => 'count' ) ) );
return $rows[0]['count'];
}
/**
* Returns an array of content objects with the content class id $contentClassID
*
* @param int $contentClassID
* @param bool $asObject Whether to return objects or not
* @param int|bool $offset Where to start fetch from, set to false to skip it.
* @param int|bool $limit Maximum number of objects to fetch, set false to skip it.
* @return eZContentObject[]|array|null
*/
static function fetchSameClassList( $contentClassID, $asObject = true, $offset = false, $limit = false )
{
$conditions = array( 'contentclass_id' => $contentClassID );
return eZContentObject::fetchFilteredList( $conditions, $offset, $limit, $asObject );
}
/**
* Returns the number of content objects with the content class id $contentClassID
*
* @param int $contentClassID
* @return int
*/
static function fetchSameClassListCount( $contentClassID )
{
$result = eZPersistentObject::fetchObjectList( eZContentObject::definition(),
array(),
array( "contentclass_id" => $contentClassID ),
false, null,
false, false,
array( array( 'operation' => 'count( * )',
'name' => 'count' ) ) );
return $result[0]['count'];
}
/**
* Returns the current version of this document.
*
* @param bool $asObject If true, returns an eZContentObjectVersion; if false, returns an array
* @return eZContentObjectVersion|array|bool
*/
function currentVersion( $asObject = true )
{
return eZContentObjectVersion::fetchVersion( $this->attribute( "current_version" ), $this->ID, $asObject );
}
/**
* Returns the published version of the object, or null if not published yet.
*
* @return int|null
*/
public function publishedVersion()
{
$params = array(
'conditions' => array(
'status' => eZContentObjectVersion::STATUS_PUBLISHED
)
);
$versions = $this->versions( false, $params );
if ( !empty( $versions ) )
{
return $versions[0]['version'];
}
return null;
}
/**
* Returns the given object version. False is returned if the versions does not exist.
*
* @param int $version
* @param bool $asObject If true, returns an eZContentObjectVersion; if false, returns an array
* @return eZContentObjectVersion|array|bool
*/
function version( $version, $asObject = true )
{
if ( $asObject )
{
global $eZContentObjectVersionCache;
if ( !isset( $eZContentObjectVersionCache ) ) // prevent PHP warning below
$eZContentObjectVersionCache = array();
if ( isset( $eZContentObjectVersionCache[$this->ID][$version] ) )
{
return $eZContentObjectVersionCache[$this->ID][$version];
}
else
{
$eZContentObjectVersionCache[$this->ID][$version] = eZContentObjectVersion::fetchVersion( $version, $this->ID, $asObject );
return $eZContentObjectVersionCache[$this->ID][$version];
}
}
else
{
return eZContentObjectVersion::fetchVersion( $version, $this->ID, $asObject );
}
}
/**
* Returns an array of eZContentObjectVersion for the current object according to the conditions in $parameters.
*
* @param bool $asObject If true, returns an eZContentObjectVersion; if false, returns an array
* @param array $parameters
* @return eZContentObjectVersion[]|array
*/
function versions( $asObject = true, $parameters = array() )
{
$conditions = array( "contentobject_id" => $this->ID );
if ( isset( $parameters['conditions'] ) )
{
if ( isset( $parameters['conditions']['status'] ) )
$conditions['status'] = $parameters['conditions']['status'];
if ( isset( $parameters['conditions']['creator_id'] ) )
$conditions['creator_id'] = $parameters['conditions']['creator_id'];
if ( isset( $parameters['conditions']['language_code'] ) )
{
$conditions['initial_language_id'] = eZContentLanguage::idByLocale( $parameters['conditions']['language_code'] );
}
if ( isset( $parameters['conditions']['initial_language_id'] ) )
{
$conditions['initial_language_id'] = $parameters['conditions']['initial_language_id'];
}
}
$sort = isset( $parameters['sort'] ) ? $parameters['sort'] : null;
$limit = isset( $parameters['limit'] ) ? $parameters['limit'] : null;
return eZPersistentObject::fetchObjectList( eZContentObjectVersion::definition(),
null, $conditions,
$sort, $limit,
$asObject );
}
/**
* Returns true if the object has any versions remaining.
*
* @return bool
*/
function hasRemainingVersions()
{
$remainingVersions = $this->versions( false );
if ( !is_array( $remainingVersions ) or
count( $remainingVersions ) == 0 )
{
return false;
}
return true;
}
/**
* Creates an initial content object version
*
* @param int $userID
* @param string|bool $initialLanguageCode
* @return eZContentObjectVersion
*/
function createInitialVersion( $userID, $initialLanguageCode = false )
{
return eZContentObjectVersion::create( $this->attribute( "id" ), $userID, 1, $initialLanguageCode );
}
/**
* Creates a new version for the language $languageCode
*
* @param string $languageCode
* @param bool $copyFromLanguageCode
* @param int|bool $copyFromVersion
* @param bool $versionCheck
* @param int $status
*
* @return eZContentObjectVersion
*/
function createNewVersionIn( $languageCode, $copyFromLanguageCode = false, $copyFromVersion = false, $versionCheck = true, $status = eZContentObjectVersion::STATUS_DRAFT )
{
return $this->createNewVersion( $copyFromVersion, $versionCheck, $languageCode, $copyFromLanguageCode, $status );
}
/**
* Creates a new version and returns it as an eZContentObjectVersion object.
*
* Transaction unsafe. If you call several transaction unsafe methods you must enclose
* the calls within a db transaction; thus within db->begin and db->commit.
*
* @param int|bool $copyFromVersion If given, that version is used to create a copy.
* @param bool $versionCheck If \c true it will check if there are too many version and remove some of them to make room for a new.
* @param string|bool $languageCode
* @param string|bool $copyFromLanguageCode
* @param int $status
*
* @return eZContentObjectVersion
*/
function createNewVersion( $copyFromVersion = false, $versionCheck = true, $languageCode = false, $copyFromLanguageCode = false, $status = eZContentObjectVersion::STATUS_DRAFT )
{
$db = eZDB::instance();
$db->begin();
// get the next available version number
$nextVersionNumber = $this->nextVersion();
if ( $copyFromVersion == false )
{
$version = $this->currentVersion();
}
else
{
$version = $this->version( $copyFromVersion );
}
if ( !$languageCode )
{
$initialLanguage = $version->initialLanguage();
if ( !$initialLanguage )
{
$initialLanguage = $this->initialLanguage();
}
if ( $initialLanguage )
{
$languageCode = $initialLanguage->attribute( 'locale' );
}
}
$copiedVersion = $this->copyVersion( $this, $version, $nextVersionNumber, false, $status, $languageCode, $copyFromLanguageCode );
// We need to make sure the copied version contains node-assignment for the existing nodes.
// This is required for BC since scripts might traverse the node-assignments and mark
// some of them for removal.
$parentMap = array();
$copiedNodeAssignmentList = $copiedVersion->attribute( 'node_assignments' );
foreach ( $copiedNodeAssignmentList as $copiedNodeAssignment )
{
$parentMap[$copiedNodeAssignment->attribute( 'parent_node' )] = $copiedNodeAssignment;
}
$nodes = $this->assignedNodes();
foreach ( $nodes as $node )
{
$remoteID = 0;
// Remove assignments which conflicts with existing nodes, but keep remote_id
if ( isset( $parentMap[$node->attribute( 'parent_node_id' )] ) )
{
$copiedNodeAssignment = $parentMap[$node->attribute( 'parent_node_id' )];
$remoteID = $copiedNodeAssignment->attribute( 'remote_id' );
$copiedNodeAssignment->purge();
}
$newNodeAssignment = $copiedVersion->assignToNode( $node->attribute( 'parent_node_id' ), $node->attribute( 'is_main' ), 0,
$node->attribute( 'sort_field' ), $node->attribute( 'sort_order' ),
$remoteID, $node->attribute( 'remote_id' ) );
// Reset execution bit
$newNodeAssignment->setAttribute( 'op_code', $newNodeAssignment->attribute( 'op_code' ) & ~1 );
$newNodeAssignment->store();
}
// Removing last item if we don't have enough space in version list
if ( $versionCheck )
{
$versionlimit = eZContentClass::versionHistoryLimit( $this->attribute( 'contentclass_id' ) );
$versionCount = $this->getVersionCount();
if ( $versionCount > $versionlimit )
{
// Remove oldest archived version
$params = array( 'conditions'=> array( 'status' => eZContentObjectVersion::STATUS_ARCHIVED ) );
$versions = $this->versions( true, $params );
if ( count( $versions ) > 0 )
{
$modified = $versions[0]->attribute( 'modified' );
$removeVersion = $versions[0];
foreach ( $versions as $version )
{
$currentModified = $version->attribute( 'modified' );
if ( $currentModified < $modified )
{
$modified = $currentModified;
$removeVersion = $version;
}
}
$removeVersion->removeThis();
}
}
}
$db->commit();
return $copiedVersion;
}
/**
* Creates a new version and returns it as an eZContentObjectVersion object.
*
* If version number is given as argument that version is used to create a copy.
*
* Transaction unsafe. If you call several transaction unsafe methods you must enclose
* the calls within a db transaction; thus within db->begin and db->commit.
*
* @param eZContentObject $newObject
* @param eZContentObjectVersion $version
* @param int $newVersionNumber
* @param int|bool $contentObjectID
* @param int $status
* @param string|bool $languageCode If false all languages will be copied, otherwise only specified by the locale code string or an array of the locale code strings.
* @param string|bool $copyFromLanguageCode
*
* @return eZContentObjectVersion
*/
function copyVersion( &$newObject, &$version, $newVersionNumber, $contentObjectID = false, $status = eZContentObjectVersion::STATUS_DRAFT, $languageCode = false, $copyFromLanguageCode = false )
{
$user = eZUser::currentUser();
$userID = $user->attribute( 'contentobject_id' );
$nodeAssignmentList = $version->attribute( 'node_assignments' );
$db = eZDB::instance();
$db->begin();
// This is part of the new 3.8 code.
foreach ( $nodeAssignmentList as $nodeAssignment )
{
// Only copy assignments which has a remote_id since it will be used in template code.
if ( $nodeAssignment->attribute( 'remote_id' ) == 0 )
{
continue;
}
$clonedAssignment = $nodeAssignment->cloneNodeAssignment( $newVersionNumber, $contentObjectID );
$clonedAssignment->setAttribute( 'op_code', eZNodeAssignment::OP_CODE_SET ); // Make sure op_code is marked to 'set' the data.
$clonedAssignment->store();
}
$currentVersionNumber = $version->attribute( "version" );
$contentObjectTranslations = $version->translations();
$clonedVersion = $version->cloneVersion( $newVersionNumber, $userID, $contentObjectID, $status );
if ( $contentObjectID != false )
{
if ( $clonedVersion->attribute( 'status' ) == eZContentObjectVersion::STATUS_PUBLISHED )
$clonedVersion->setAttribute( 'status', eZContentObjectVersion::STATUS_DRAFT );
}
$clonedVersion->store();
// We copy related objects before the attributes, this means that the related objects
// are available once the datatype code is run.
$this->copyContentObjectRelations( $currentVersionNumber, $newVersionNumber, $contentObjectID );
$languageCodeToCopy = false;
if ( $languageCode && in_array( $languageCode, $this->availableLanguages() ) )
{
$languageCodeToCopy = $languageCode;
}
if ( $copyFromLanguageCode && in_array( $copyFromLanguageCode, $this->availableLanguages() ) )
{
$languageCodeToCopy = $copyFromLanguageCode;
}
$haveCopied = false;
if ( !$languageCode || $languageCodeToCopy )
{
foreach ( $contentObjectTranslations as $contentObjectTranslation )
{
if ( $languageCode != false && $contentObjectTranslation->attribute( 'language_code' ) != $languageCodeToCopy )
{
continue;
}
$contentObjectAttributes = $contentObjectTranslation->objectAttributes();
foreach ( $contentObjectAttributes as $attribute )
{
$clonedAttribute = $attribute->cloneContentObjectAttribute( $newVersionNumber, $currentVersionNumber, $contentObjectID, $languageCode );
$clonedAttribute->sync();
eZDebugSetting::writeDebug( 'kernel-content-object-copy', $clonedAttribute, 'copyVersion:cloned attribute' );
}
$haveCopied = true;
}
}
if ( !$haveCopied && $languageCode )
{
$class = $this->contentClass();
$classAttributes = $class->fetchAttributes();
foreach ( $classAttributes as $classAttribute )
{
if ( $classAttribute->attribute( 'can_translate' ) == 1 )
{
$classAttribute->instantiate( $contentObjectID? $contentObjectID: $this->attribute( 'id' ), $languageCode, $newVersionNumber );
}
else
{
// If attribute is NOT Translatable we should check isAlwaysAvailable(),
// For example,
// if initial_language_id is 4 and the attribute is always available
// language_id will be 5 in ezcontentobject_version/ezcontentobject_attribute,
// this means it uses language ID 4 but also has the bit 0 set to 1 (a reservered bit),
// You can read about this in the document in doc/features/3.8/.
$initialLangID = !$this->isAlwaysAvailable() ? $this->attribute( 'initial_language_id' ) : $this->attribute( 'initial_language_id' ) | 1;
$contentAttribute = eZContentObjectAttribute::fetchByClassAttributeID( $classAttribute->attribute( 'id' ),
$this->attribute( 'id' ),
$this->attribute( 'current_version' ),
$initialLangID );
if ( $contentAttribute )
{
$newAttribute = $contentAttribute->cloneContentObjectAttribute( $newVersionNumber, $currentVersionNumber, $contentObjectID, $languageCode );
$newAttribute->sync();
}
else
{
$classAttribute->instantiate( $contentObjectID? $contentObjectID: $this->attribute( 'id' ), $languageCode, $newVersionNumber );
}
}
}
}
if ( $languageCode )
{
$clonedVersion->setAttribute( 'initial_language_id', eZContentLanguage::idByLocale( $languageCode ) );
$clonedVersion->updateLanguageMask();
}
$db->commit();
return $clonedVersion;
}
/**
* Creates a new content object instance and stores it.
*
* @param string $name
* @param int $contentclassID
* @param int $userID
* @param int $sectionID
* @param int $version
* @param string|bool $languageCode
* @return eZContentObject
*/
static function create( $name, $contentclassID, $userID, $sectionID = 1, $version = 1, $languageCode = false )
{
if ( $languageCode == false )
{
$languageCode = eZContentObject::defaultLanguage();
}
$languageID = eZContentLanguage::idByLocale( $languageCode );
$row = array(
"name" => $name,
"current_version" => $version,
'initial_language_id' => $languageID,
'language_mask' => $languageID,
"contentclass_id" => $contentclassID,
"permission_id" => 1,
"parent_id" => 0,
"main_node_id" => 0,
"owner_id" => $userID,
"section_id" => $sectionID,
'remote_id' => eZRemoteIdUtility::generate( 'object' ) );
return new eZContentObject( $row );
}
/**
* Resets certain attributes of the content object on clone and resets the data map
*/
function __clone()
{
$this->setAttribute( 'id', null );
$this->setAttribute( 'published', time() );
$this->setAttribute( 'modified', time() );
$this->resetDataMap();
}
/**
* Makes a copy of the object which is stored and then returns it.
*
* Transaction unsafe. If you call several transaction unsafe methods you must enclose
* the calls within a db transaction; thus within db->begin and db->commit.
*
* @param bool $allVersions If true, all versions are copied. If false, only the latest version is copied
* @return eZContentObject
*/
function copy( $allVersions = true )
{
eZDebugSetting::writeDebug( 'kernel-content-object-copy', 'Copy start, all versions=' . ( $allVersions ? 'true' : 'false' ), 'copy' );
$user = eZUser::currentUser();
$userID = $user->attribute( 'contentobject_id' );
$contentObject = clone $this;
$contentObject->setAttribute( 'current_version', 1 );
$contentObject->setAttribute( 'owner_id', $userID );
$contentObject->setAttribute( 'remote_id', eZRemoteIdUtility::generate( 'object' ) );
$db = eZDB::instance();
$db->begin();
$contentObject->store();
$originalObjectID = $this->attribute( 'id' );
$contentObjectID = $contentObject->attribute( 'id' );
$db->query( "INSERT INTO ezcobj_state_link (contentobject_state_id, contentobject_id)
SELECT contentobject_state_id, $contentObjectID FROM ezcobj_state_link WHERE contentobject_id = $originalObjectID" );
$contentObject->setName( $this->attribute('name') );
eZDebugSetting::writeDebug( 'kernel-content-object-copy', $contentObject, 'contentObject' );
$versionList = array();
if ( $allVersions )
{
$versions = $this->versions();
foreach( $versions as $version )
{
$versionList[$version->attribute( 'version' )] = $version;
}
}
else
{
$versionList[1] = $this->currentVersion();
}
foreach ( $versionList as $versionNumber => $currentContentObjectVersion )
{
$currentVersionNumber = $currentContentObjectVersion->attribute( 'version' );
$contentObject->setName( $currentContentObjectVersion->name(), $versionNumber );
foreach( $contentObject->translationStringList() as $languageCode )
{
$contentObject->setName( $currentContentObjectVersion->name( false, $languageCode ), $versionNumber, $languageCode );
}
$contentObjectVersion = $this->copyVersion( $contentObject, $currentContentObjectVersion,
$versionNumber, $contentObject->attribute( 'id' ),
false );
if ( $currentVersionNumber == $this->attribute( 'current_version' ) )
{
$parentMap = array();
$copiedNodeAssignmentList = $contentObjectVersion->attribute( 'node_assignments' );
foreach ( $copiedNodeAssignmentList as $copiedNodeAssignment )
{
$parentMap[$copiedNodeAssignment->attribute( 'parent_node' )] = $copiedNodeAssignment;
}
// Create node-assignment from all current published nodes
$nodes = $this->assignedNodes();
foreach( $nodes as $node )
{
$remoteID = eZRemoteIdUtility::generate( 'object' );
// Remove assignments which conflicts with existing nodes, but keep remote_id
if ( isset( $parentMap[$node->attribute( 'parent_node_id' )] ) )
{
$copiedNodeAssignment = $parentMap[$node->attribute( 'parent_node_id' )];
unset( $parentMap[$node->attribute( 'parent_node_id' )] );
$remoteID = $copiedNodeAssignment->attribute( 'remote_id' );
$copiedNodeAssignment->purge();
}
$contentObjectVersion->assignToNode(
$node->attribute( 'parent_node_id' ),
$node->attribute( 'is_main' ),
0,
$node->attribute( 'sort_field' ),
$node->attribute( 'sort_order' ),
$remoteID
);
}
}
eZDebugSetting::writeDebug( 'kernel-content-object-copy', $contentObjectVersion, 'Copied version' );
}
// Set version number
if ( $allVersions )
$contentObject->setAttribute( 'current_version', $this->attribute( 'current_version' ) );
$contentObject->setAttribute( 'status', eZContentObject::STATUS_DRAFT );
$contentObject->store();
$db->commit();
eZDebugSetting::writeDebug( 'kernel-content-object-copy', 'Copy done', 'copy' );
return $contentObject;
}
/**
* Copies the given version of the object and creates a new current version.
*
* Transaction unsafe. If you call several transaction unsafe methods you must enclose
* the calls within a db transaction; thus within db->begin and db->commit.
*
* @param int $version
* @param string|bool $language
*
* @return int The new version number
*/
function copyRevertTo( $version, $language = false )
{
$versionObject = $this->createNewVersionIn( $language, false, $version );
return $versionObject->attribute( 'version' );
}
/**
* Fixes reverse relations
*
* @see eZObjectRelationListType::fixRelatedObjectItem()
*
* @param int $objectID
* @param string|bool $mode See eZObjectRelationListType::fixRelatedObjectItem() for valid modes
* @param bool $clearCacheIfEnabled If set to false cache won't be cleared
*/
static function fixReverseRelations( $objectID, $mode = false, $clearCacheIfEnabled = true )
{
$db = eZDB::instance();
$objectID = (int) $objectID;
// Finds all the attributes that store relations to the given object.
$result = $db->arrayQuery( "SELECT attr.*
FROM ezcontentobject_link link,
ezcontentobject_attribute attr
WHERE link.from_contentobject_id=attr.contentobject_id AND
link.from_contentobject_version=attr.version AND
link.contentclassattribute_id=attr.contentclassattribute_id AND
link.to_contentobject_id=$objectID" );
if ( count( $result ) > 0 )
{
$objectIDList = array();
foreach( $result as $row )
{
$attr = new eZContentObjectAttribute( $row );
$dataType = $attr->dataType();
$dataType->fixRelatedObjectItem( $attr, $objectID, $mode );
$objectIDList[] = $attr->attribute( 'contentobject_id' );
}
if ( $clearCacheIfEnabled && eZINI::instance()->variable( 'ContentSettings', 'ViewCaching' ) === 'enabled' )
eZContentCacheManager::clearObjectViewCacheArray( $objectIDList );
}
}
/**
* Deletes the current object, all versions and translations, and corresponding tree nodes from the database
*
* Transaction unsafe. If you call several transaction unsafe methods you must enclose
* the calls within a db transaction; thus within db->begin and db->commit.
*/
function purge()
{
$delID = $this->ID;
// Who deletes which content should be logged.
eZAudit::writeAudit( 'content-delete', array( 'Object ID' => $delID, 'Content Name' => $this->attribute( 'name' ),
'Comment' => 'Purged the current object: eZContentObject::purge()' ) );
$db = eZDB::instance();
$db->begin();
$attrOffset = 0;
$attrLimit = 20;
while (
$contentobjectAttributes = $this->allContentObjectAttributes(
$delID, true, array( 'limit' => $attrLimit, 'offset' => $attrOffset )
)
)
{
foreach ( $contentobjectAttributes as $contentobjectAttribute )
{
$dataType = $contentobjectAttribute->dataType();
if ( !$dataType )
continue;
$dataType->deleteStoredObjectAttribute( $contentobjectAttribute );
}
$attrOffset += $attrLimit;
}
eZInformationCollection::removeContentObject( $delID );
eZContentObjectTrashNode::purgeForObject( $delID );
$db->query( "DELETE FROM ezcontentobject_tree
WHERE contentobject_id='$delID'" );
$db->query( "DELETE FROM ezcontentobject_attribute
WHERE contentobject_id='$delID'" );
$db->query( "DELETE FROM ezcontentobject_version
WHERE contentobject_id='$delID'" );
$db->query( "DELETE FROM ezcontentobject_name
WHERE contentobject_id='$delID'" );
$db->query( "DELETE FROM ezcobj_state_link WHERE contentobject_id=$delID" );
$db->query( "DELETE FROM ezcontentobject
WHERE id='$delID'" );
$db->query( "DELETE FROM eznode_assignment
WHERE contentobject_id = '$delID'" );
$db->query( "DELETE FROM ezuser_role
WHERE contentobject_id = '$delID'" );
$db->query( "DELETE FROM ezuser_discountrule
WHERE contentobject_id = '$delID'" );
eZContentObject::fixReverseRelations( $delID, 'remove' );
eZSearch::removeObjectById( $delID );
// Check if deleted object is in basket/wishlist
$sql = 'SELECT DISTINCT ezproductcollection_item.productcollection_id
FROM ezbasket, ezwishlist, ezproductcollection_item
WHERE ( ezproductcollection_item.productcollection_id=ezbasket.productcollection_id OR
ezproductcollection_item.productcollection_id=ezwishlist.productcollection_id ) AND
ezproductcollection_item.contentobject_id=' . $delID;
$rows = $db->arrayQuery( $sql );
if ( count( $rows ) > 0 )
{
$countElements = 50;
$deletedArray = array();
// Create array of productCollectionID will be removed from ezwishlist and ezproductcollection_item
foreach ( $rows as $row )
{
$deletedArray[] = $row['productcollection_id'];
}
// Split $deletedArray into several arrays with $countElements values
$splitted = array_chunk( $deletedArray, $countElements );
// Remove eZProductCollectionItem and eZWishList
foreach ( $splitted as $value )
{
eZPersistentObject::removeObject( eZProductCollectionItem::definition(), array( 'productcollection_id' => array( $value, '' ) ) );
eZPersistentObject::removeObject( eZWishList::definition(), array( 'productcollection_id' => array( $value, '' ) ) );
}
}
$db->query( 'UPDATE ezproductcollection_item
SET contentobject_id = 0
WHERE contentobject_id = ' . $delID );
// Cleanup relations in two steps to avoid locking table for to long
$db->query( "DELETE FROM ezcontentobject_link
WHERE from_contentobject_id = '$delID'" );
$db->query( "DELETE FROM ezcontentobject_link
WHERE to_contentobject_id = '$delID'" );
// Cleanup properties: LastVisit, Creator, Owner
$db->query( "DELETE FROM ezuservisit
WHERE user_id = '$delID'" );
$db->query( "UPDATE ezcontentobject_version
SET creator_id = 0
WHERE creator_id = '$delID'" );
$db->query( "UPDATE ezcontentobject
SET owner_id = 0
WHERE owner_id = '$delID'" );
if ( isset( $GLOBALS["eZWorkflowTypeObjects"] ) and is_array( $GLOBALS["eZWorkflowTypeObjects"] ) )
{
$registeredTypes =& $GLOBALS["eZWorkflowTypeObjects"];
}
else
{
$registeredTypes = eZWorkflowType::fetchRegisteredTypes();
}
// Cleanup ezworkflow_event etc...
foreach ( array_keys( $registeredTypes ) as $registeredTypeKey )
{
$registeredType = $registeredTypes[$registeredTypeKey];
$registeredType->cleanupAfterRemoving( array( 'DeleteContentObject' => $delID ) );
}
$db->commit();
}
/**
* Archives the current object and removes assigned nodes
*
* Transaction unsafe. If you call several transaction unsafe methods you must enclose
* the calls within a db transaction; thus within db->begin and db->commit.
*
* @param int $nodeID
*/
function removeThis( $nodeID = null )
{
$delID = $this->ID;
// Who deletes which content should be logged.
eZAudit::writeAudit( 'content-delete', array( 'Object ID' => $delID, 'Content Name' => $this->attribute( 'name' ),
'Comment' => 'Setted archived status for the current object: eZContentObject::remove()' ) );
$nodes = $this->attribute( 'assigned_nodes' );
if ( $nodeID === null or count( $nodes ) <= 1 )
{
$db = eZDB::instance();
$db->begin();
$mainNodeKey = false;
foreach ( $nodes as $key => $node )
{
if ( $node->attribute( 'main_node_id' ) == $node->attribute( 'node_id' ) )
{
$mainNodeKey = $key;
}
else
{
$node->removeThis();
}
}
if ( $mainNodeKey !== false )
{
$nodes[$mainNodeKey]->removeNodeFromTree( true );
}
$this->setAttribute( 'status', eZContentObject::STATUS_ARCHIVED );
eZSearch::removeObjectById( $delID );
$this->store();
eZContentObject::fixReverseRelations( $delID, 'trash' );
// Delete stored attribute from other tables
$db->commit();
}
else if ( $nodeID !== null )
{
$node = eZContentObjectTreeNode::fetch( $nodeID , false );
if ( is_object( $node ) )
{
if ( $node->attribute( 'main_node_id' ) == $nodeID )
{
$db = eZDB::instance();
$db->begin();
foreach ( $additionalNodes as $additionalNode )
{
if ( $additionalNode->attribute( 'node_id' ) != $node->attribute( 'main_node_id' ) )
{
$additionalNode->remove();
}
}
$node->removeNodeFromTree( true );
$this->setAttribute( 'status', eZContentObject::STATUS_ARCHIVED );
eZSearch::removeObjectById( $delID );
$this->store();
eZContentObject::fixReverseRelations( $delID, 'trash' );
$db->commit();
}
else
{
eZContentObjectTreeNode::removeNode( $nodeID );
}
}
}
else
{
eZContentObjectTreeNode::removeNode( $nodeID );
}
}
/**
* Removes old internal drafts by the specified user associated for the past time span given by $timeDuration
*
* @param int|bool $userID The ID of the user to cleanup for, if false it will use the current user.
* @param int $timeDuration default time duration for internal drafts 60*60*24 seconds (1 day)
*/
function cleanupInternalDrafts( $userID = false, $timeDuration = 86400 )
{
if ( !is_numeric( $timeDuration ) ||
$timeDuration < 0 )
{
eZDebug::writeError( "The time duration must be a positive numeric value (timeDuration = $timeDuration)", __METHOD__ );
return;
}
if ( $userID === false )
{
$userID = eZUser::currentUserID();
}
// Fetch all draft/temporary versions by specified user
$parameters = array( 'conditions' => array( 'status' => eZContentObjectVersion::STATUS_INTERNAL_DRAFT,
'creator_id' => $userID ) );
// Remove temporary drafts which are old.
$expiryTime = time() - $timeDuration; // only remove drafts older than time duration (default is 1 day)
foreach ( $this->versions( true, $parameters ) as $possibleVersion )
{
if ( $possibleVersion->attribute( 'modified' ) < $expiryTime )
{
$possibleVersion->removeThis();
}
}
}
/**
* Removes all old internal drafts by the specified user for the past time span given by $timeDuration
*
* @param int|bool $userID The ID of the user to cleanup for, if false it will use the current user.
* @param int $timeDuration default time duration for internal drafts 60*60*24 seconds (1 day)
*/
static function cleanupAllInternalDrafts( $userID = false, $timeDuration = 86400 ) //
{
if ( !is_numeric( $timeDuration ) ||
$timeDuration < 0 )
{
eZDebug::writeError( "The time duration must be a positive numeric value (timeDuration = $timeDuration)", __METHOD__ );
return;
}
if ( $userID === false )
{
$userID = eZUser::currentUserID();
}
// Remove all internal drafts
$untouchedDrafts = eZContentObjectVersion::fetchForUser( $userID, eZContentObjectVersion::STATUS_INTERNAL_DRAFT );
$expiryTime = time() - $timeDuration; // only remove drafts older than time duration (default is 1 day)
foreach ( $untouchedDrafts as $untouchedDraft )
{
if ( $untouchedDraft->attribute( 'modified' ) < $expiryTime )
{
$untouchedDraft->removeThis();
}
}
}
/**
* Fetches all attributes from any versions of the content object
*
* @param int $contentObjectID
* @param bool $asObject
* @param array|null $limit the limit array passed to {@see eZPersistentObject::fetchObjectList}
* @return eZContentObjectAttribute[]|array|null
*/
function allContentObjectAttributes( $contentObjectID, $asObject = true, $limit = null )
{
return eZPersistentObject::fetchObjectList( eZContentObjectAttribute::definition(),
null,
array("contentobject_id" => $contentObjectID ),
null,
$limit,
$asObject );
}
/**
* Fetches the attributes for the current published version of the object.
*
* @todo fix using of $asObject parameter
* @todo fix condition for getting attribute from cache
* @todo probably need to move method to eZContentObjectVersion class
*
* @param bool $asObject
* @param int|bool $version
* @param string|bool $language
* @param int|bool $contentObjectAttributeID
* @param bool $distinctItemsOnly
* @return eZContentObjectAttribute[]|array
*/
function contentObjectAttributes( $asObject = true, $version = false, $language = false, $contentObjectAttributeID = false, $distinctItemsOnly = false )
{
$db = eZDB::instance();
if ( $version == false )
{
$version = $this->CurrentVersion;
}
else
{
$version = (int) $version;
}
if ( $language === false )
{
$language = $this->CurrentLanguage;
}
if ( is_string( $language ) )
$language = $db->escapeString( $language );
if ( $contentObjectAttributeID !== false )
$contentObjectAttributeID =(int) $contentObjectAttributeID;
if ( !$language || !isset( $this->ContentObjectAttributes[$version][$language] ) )
{
$versionText = "AND ezcontentobject_attribute.version = '$version'";
if ( $language )
{
$languageText = "AND ezcontentobject_attribute.language_code = '$language'";
}
else
{
$languageText = "AND ".eZContentLanguage::sqlFilter( 'ezcontentobject_attribute', 'ezcontentobject_version' );
}
$attributeIDText = false;
if ( $contentObjectAttributeID )
$attributeIDText = "AND ezcontentobject_attribute.id = '$contentObjectAttributeID'";
$distinctText = false;
if ( $distinctItemsOnly )
$distinctText = "GROUP BY ezcontentobject_attribute.id";
$query = "SELECT ezcontentobject_attribute.*, ezcontentclass_attribute.identifier as identifier FROM
ezcontentobject_attribute, ezcontentclass_attribute, ezcontentobject_version
WHERE
ezcontentclass_attribute.version = '0' AND
ezcontentclass_attribute.id = ezcontentobject_attribute.contentclassattribute_id AND
ezcontentobject_version.contentobject_id = '$this->ID' AND
ezcontentobject_version.version = '$version' AND
ezcontentobject_attribute.contentobject_id = '$this->ID' $versionText $languageText $attributeIDText
$distinctText
ORDER BY
ezcontentclass_attribute.placement ASC,
ezcontentobject_attribute.language_code ASC";
$attributeArray = $db->arrayQuery( $query );
if ( !$language && $attributeArray )
{
$language = $attributeArray[0]['language_code'];
$this->CurrentLanguage = $language;
}
$returnAttributeArray = array();
foreach ( $attributeArray as $attribute )
{
$attr = new eZContentObjectAttribute( $attribute );
$attr->setContentClassAttributeIdentifier( $attribute['identifier'] );
$returnAttributeArray[] = $attr;
}
if ( $language !== null and $version !== null )
{
$this->ContentObjectAttributes[$version][$language] = $returnAttributeArray;
}
}
else
{
$returnAttributeArray = $this->ContentObjectAttributes[$version][$language];
}
return $returnAttributeArray;
}
/**
* Initializes the cached copy of the content object attributes for the given version and language
*
* @param eZContentObjectAttribute[] $attributes
* @param int $version
* @param string $language
*/
function setContentObjectAttributes( &$attributes, $version, $language )
{
$this->ContentObjectAttributes[$version][$language] = $attributes;
}
/**
* Fetches the attributes for an array of objects or nodes
*
* @param eZContentObject[]|eZContentObjectTreeNode[] $objList
* @param bool $asObject
*/
static function fillNodeListAttributes( $objList, $asObject = true )
{
$db = eZDB::instance();
if ( count( $objList ) > 0 )
{
$objectArray = array();
$tmpLanguageObjectList = array();
$whereSQL = '';
$count = count( $objList );
$i = 0;
foreach ( $objList as $obj )
{
if ( $obj instanceOf eZContentObject )
$object = $obj;
else
$object = $obj->attribute( 'object' );
$language = $object->currentLanguage();
$tmpLanguageObjectList[$object->attribute( 'id' )] = $language;
$objectArray = array( 'id' => $object->attribute( 'id' ),
'language' => $language,
'version' => $object->attribute( 'current_version' ) );
$whereSQL .= "( ezcontentobject_attribute.version = '" . $object->attribute( 'current_version' ) . "' AND
ezcontentobject_attribute.contentobject_id = '" . $object->attribute( 'id' ) . "' AND
ezcontentobject_attribute.language_code = '" . $language . "' ) ";
$i++;
if ( $i < $count )
$whereSQL .= ' OR ';
}
$query = "SELECT ezcontentobject_attribute.*, ezcontentclass_attribute.identifier as identifier FROM
ezcontentobject_attribute, ezcontentclass_attribute
WHERE
ezcontentclass_attribute.version = '0' AND
ezcontentclass_attribute.id = ezcontentobject_attribute.contentclassattribute_id AND
( $whereSQL )
ORDER BY
ezcontentobject_attribute.contentobject_id, ezcontentclass_attribute.placement ASC";
$attributeArray = $db->arrayQuery( $query );
$tmpAttributeObjectList = array();
$returnAttributeArray = array();
foreach ( $attributeArray as $attribute )
{
$attr = new eZContentObjectAttribute( $attribute );
$attr->setContentClassAttributeIdentifier( $attribute['identifier'] );
$tmpAttributeObjectList[$attr->attribute( 'contentobject_id' )][] = $attr;
}
foreach ( $objList as $obj )
{
if ( $obj instanceOf eZContentObject )
{
$obj->setContentObjectAttributes( $tmpAttributeObjectList[$obj->attribute( 'id' )],
$obj->attribute( 'current_version' ),
$tmpLanguageObjectList[$obj->attribute( 'id' )] );
}
else
{
$object = $obj->attribute( 'object' );
$object->setContentObjectAttributes( $tmpAttributeObjectList[$object->attribute( 'id' )],
$object->attribute( 'current_version' ),
$tmpLanguageObjectList[$object->attribute( 'id' )] );
$obj->setContentObject( $object );
}
}
}
}
/**
* Resets the object's input relation list
*/
function resetInputRelationList()
{
$this->InputRelationList = array( eZContentObject::RELATION_EMBED => array(),
eZContentObject::RELATION_LINK => array() );
}
/**
* @param int[] $addingIDList
* @param int $relationType
*/
function appendInputRelationList( $addingIDList, $relationType )
{
if ( !is_array( $addingIDList ) )
{
$addingIDList = array( ( int ) $addingIDList );
}
elseif ( !count( $addingIDList ) )
{
return;
}
$relationType = ( int ) $relationType;
if ( !$this->InputRelationList )
{
$this->resetInputRelationList();
}
foreach ( array_keys( $this->InputRelationList ) as $inputRelationType )
{
if ( $inputRelationType & $relationType )
{
$this->InputRelationList[$inputRelationType] = array_merge( $this->InputRelationList[$inputRelationType], $addingIDList );
}
}
}
/**
* @param int|bool $editVersion
* @return bool
*/
function commitInputRelations( $editVersion )
{
foreach ( $this->InputRelationList as $relationType => $relatedObjectIDArray )
{
$oldRelatedObjectArray = $this->relatedObjects( $editVersion, false, 0, false, array( 'AllRelations' => $relationType ) );
foreach ( $oldRelatedObjectArray as $oldRelatedObject )
{
$oldRelatedObjectID = $oldRelatedObject->ID;
if ( !in_array( $oldRelatedObjectID, $relatedObjectIDArray ) )
{
$this->removeContentObjectRelation( $oldRelatedObjectID, $editVersion, 0, $relationType );
}
$relatedObjectIDArray = array_diff( $relatedObjectIDArray, array( $oldRelatedObjectID ) );
}
foreach ( $relatedObjectIDArray as $relatedObjectID )
{
$this->addContentObjectRelation( $relatedObjectID, $editVersion, 0, $relationType );
}
}
return true;
}
/**
* @param eZContentObjectAttribute[] $contentObjectAttributes
* @param string $attributeDataBaseName
* @param array|bool $inputParameters
* @param array $parameters
* @return array
*/
function validateInput( $contentObjectAttributes, $attributeDataBaseName,
$inputParameters = false, $parameters = array() )
{
$result = array( 'unvalidated-attributes' => array(),
'validated-attributes' => array(),
'status-map' => array(),
'require-fixup' => false,
'input-validated' => true );
$parameters = array_merge( array( 'prefix-name' => false ),
$parameters );
if ( $inputParameters )
{
$result['unvalidated-attributes'] =& $inputParameters['unvalidated-attributes'];
$result['validated-attributes'] =& $inputParameters['validated-attributes'];
}
$unvalidatedAttributes =& $result['unvalidated-attributes'];
$validatedAttributes =& $result['validated-attributes'];
$statusMap =& $result['status-map'];
if ( !$inputParameters )
$inputParameters = array( 'unvalidated-attributes' => &$unvalidatedAttributes,
'validated-attributes' => &$validatedAttributes );
$requireFixup =& $result['require-fixup'];
$inputValidated =& $result['input-validated'];
$http = eZHTTPTool::instance();
$this->resetInputRelationList();
$editVersion = null;
$defaultLanguage = $this->initialLanguageCode();
foreach( $contentObjectAttributes as $contentObjectAttribute )
{
$contentClassAttribute = $contentObjectAttribute->contentClassAttribute();
$editVersion = $contentObjectAttribute->attribute('version');
// Check if this is a translation
$currentLanguage = $contentObjectAttribute->attribute( 'language_code' );
$isTranslation = false;
if ( $currentLanguage != $defaultLanguage )
$isTranslation = true;
// If current attribute is a translation
// Check if this attribute can be translated
// If not do not validate, since the input will be copyed from the original
$doNotValidate = false;
if ( $isTranslation )
{
if ( !$contentClassAttribute->attribute( 'can_translate' ) )
$doNotValidate = true;
}
if ( $doNotValidate == true )
{
$status = eZInputValidator::STATE_ACCEPTED;
}
else
{
$status = $contentObjectAttribute->validateInput( $http, $attributeDataBaseName,
$inputParameters, $parameters );
}
$statusMap[$contentObjectAttribute->attribute( 'id' )] = array( 'value' => $status,
'attribute' => $contentObjectAttribute );
if ( $status == eZInputValidator::STATE_INTERMEDIATE )
$requireFixup = true;
else if ( $status == eZInputValidator::STATE_INVALID )
{
$inputValidated = false;
$dataType = $contentObjectAttribute->dataType();
$attributeName = $dataType->attribute( 'information' );
$attributeName = $attributeName['name'];
$description = $contentObjectAttribute->attribute( 'validation_error' );
$validationNameArray[] = $contentClassAttribute->attribute( 'name' );
$validationName = implode( '->', $validationNameArray );
$hasValidationError = $contentObjectAttribute->attribute( 'has_validation_error' );
if ( $hasValidationError )
{
if ( !$description )
$description = false;
$validationNameArray = array();
if ( $parameters['prefix-name'] )
$validationNameArray = $parameters['prefix-name'];
}
else
{
if ( !$description )
$description = 'unknown error';
}
$unvalidatedAttributes[] = array( 'id' => $contentObjectAttribute->attribute( 'id' ),
'identifier' => $contentClassAttribute->attribute( 'identifier' ),
'name' => $validationName,
'description' => $description );
}
else if ( $status == eZInputValidator::STATE_ACCEPTED )
{
$dataType = $contentObjectAttribute->dataType();
$attributeName = $dataType->attribute( 'information' );
$attributeName = $attributeName['name'];
if ( $contentObjectAttribute->attribute( 'validation_log' ) != null )
{
$description = $contentObjectAttribute->attribute( 'validation_log' );
if ( !$description )
$description = false;
$validationName = $contentClassAttribute->attribute( 'name' );
if ( $parameters['prefix-name'] )
$validationName = $parameters['prefix-name'] . '->' . $validationName;
$validatedAttributes[] = array( 'id' => $contentObjectAttribute->attribute( 'id' ),
'identifier' => $contentClassAttribute->attribute( 'identifier' ),
'name' => $validationName,
'description' => $description );
}
}
}
if ( $editVersion !== null )
{
$this->commitInputRelations( $editVersion );
}
$this->resetInputRelationList();
return $result;
}
/**
* @param eZContentObjectAttribute[] $contentObjectAttributes
* @param string $attributeDataBaseName
*/
function fixupInput( $contentObjectAttributes, $attributeDataBaseName )
{
$http = eZHTTPTool::instance();
foreach ( $contentObjectAttributes as $contentObjectAttribute )
{
$contentObjectAttribute->fixupInput( $http, $attributeDataBaseName );
}
}
/**
* @param eZContentObjectAttribute[] $contentObjectAttributes
* @param string $attributeDataBaseName
* @param array $customActionAttributeArray
* @param array $customActionParameters
* @return array
*/
function fetchInput( $contentObjectAttributes, $attributeDataBaseName,
$customActionAttributeArray, $customActionParameters )
{
// Global variable to cache datamaps
global $eZContentObjectDataMapCache;