EZ Publish Import Operator
Views:
This is part of an extention to eZ Publish to allow the automatic CRUD of content. While makeing the extension a good deal of inspiration and a certain amount of code was taken from the Data Import Extension for eZ Publish, written by Marius Eliassen and Philipp Kamps.
It relies on PHP Error Handling and PHP Patterns.
<?php
/**
* @package eZData
* @copyright Kieran Whitbread 2009-2010
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*/
abstract class eZData_ImportOperator {
protected $source = null;
protected $userId = 14; // 14 = the Administrator User.
protected $targetContentClass = null;
protected $targetLanguage = null;
protected $parentNode = 261;
protected $contentObject = null;
protected $contentObjectVersion = null;
protected $nodePriority = 0;
public function __construct(eZData_Model $source)
{
$this->source = $source;
if (eZUser::currentUserID() !== $this->getUserId())
{
$user = eZUser::fetch($this->getUserId());
eZUser::setCurrentlyLoggedInUser($user, $this->getUserId());
}
}
protected function createContentObject()
{
if (!$this->contentObject)
{
$class = eZContentClass::fetchByIdentifier($this->getTargetContentClass());
if($class)
{
$object = $class->instantiate($this->getUserId(), 0, false, $this->targetLanguage);
if (!$object)
{
trigger_error("Could not create new eZContent Object using eZContentClass id '{$this->getTargetContentClass()}'", E_USER_ERROR);
}
$object->setAttribute('remote_id', $this->source->getRemoteId());
$object->store();
$this->contentObject = $object;
$this->contentObject->fetchDataMap();
}
else
{
trigger_error("Could not create an instance of eZContentClass using id '{$this->getTargetContentClass()}'", E_USER_ERROR);
}
}
return $this->contentObject;
}
protected function createContentObjectVersion()
{
if ($this->contentObject)
{
$version = $this->contentObject->createNewVersion(false, false, $this->getTargetLanguage());
$this->contentObjectVersion = $version;
if (!$this->contentObjectVersion)
{
trigger_error("Unable to create a new Content Object Version", E_USER_WARNING);
}
return $this->contentObjectVersion;
}
else
{
trigger_error("There is no content object available", E_USER_ERROR);
}
}
/**
* fetches an instance of an eZ Publish Content Object.
*
* @return eZContentObject
* @author Kieran Whitbread
**/
protected function getContentObject()
{
if (!$this->contentObject)
{
$this->contentObject = eZContentObject::fetchByRemoteID($this->source->getRemoteId());
if (!$this->contentObject)
{
return null;
}
$this->contentObject->setAttribute('owner_id', $this->getUserId());
$this->contentObject->store();
$this->contentObject->fetchDataMap();
}
return $this->contentObject;
}
protected function getContentObjectVersion()
{
if ($this->contentObject)
{
$version = $this->contentObject->currentVersion();
$this->contentObjectVersion = $version;
}
return $this->contentObjectVersion;
}
/**
* @deprecated
* @return void
* @author Kieran Whitbread
**/
protected function getDataTypeForAttribute(eZContentObjectAttribute $attribute)
{
$attrDatatype = $attribute->attribute('data_type_string');
switch ($attrDatatype)
{
case 'ezboolean':
$dataType = 'data_int';
break;
case 'ezdate':
$dataType = 'data_int';
break;
case 'ezdatetime':
$dataType = 'data_int';
break;
case 'ezimage':
$dataType = 'data_text';
break;
case 'ezinteger':
$dataType = 'data_int';
break;
case 'ezisbn':
$dataType = 'data_text';
break;
case 'ezkeyword':
$dataType = false;
break;
case 'ezobjectrelation':
$dataType = false;
break;
case 'ezobjectrelationlist':
$dataType = false;
break;
case 'ezstring':
$dataType = 'data_text';
break;
case 'ezurl':
$dataType = 'data_text';
break;
default:
$dataType = false;
break;
}
return $dataType;
}
public function getNodePriority()
{
return $this->nodePriority;
}
public function getParentNodeId()
{
return $this->parentNode;
}
public function getTargetContentClass()
{
return $this->targetContentClass;
}
public function getTargetLanguage()
{
return $this->targetLanguage;
}
public function getUserId()
{
return $this->userId;
}
public function import($updateExisting = true)
{
if (!$this->contentObject)
{
$this->getContentObject();
if ($this->contentObject && !$updateExisting)
{
return null;
}
elseif ($this->contentObject)
{
// There was an existing object we could load, therefore our changes should be made to
// a new version of the object.
$this->createContentObjectVersion();
}
elseif (!$this->contentObject)
{
// Could not load an existing object, try to create one
$this->createContentObject();
// it's a new object so make changes to the initial "version 1"
// which was created at the same time as the object was created.
$this->getContentObjectVersion();
}
}
if (!$this->contentObject)
{
NinjaError::trigger(__METHOD__." could neither load nor create content object", E_USER_ERROR, 1);
return null;
}
if (!$this->contentObject->attribute('main_node_id'))
{
// this object is new or was pulled out of the archive and has no node assignment. make one.
// Assign object to node
$nodeAssignment = eZNodeAssignment::create(
array(
'contentobject_id' => $this->contentObject->attribute('id'),
'contentobject_version' => $this->contentObjectVersion->attribute('version'),
'parent_node' => $this->getParentNodeId(),
'is_main' => 1,
'user_id' => $this->getUserId(),
)
);
if($nodeAssignment)
{
$nodeAssignment->store();
$this->contentObject->sync();
}
}
$nodes = $this->contentObject->attribute('assigned_nodes');
foreach ($nodes as $node)
{
if ($node->attribute('main_node_id') == $node->attribute('node_id') && $node->attribute('is_hidden'))
{
eZContentObjectTreeNode::unhideSubTree($node);
}
}
$this->updateContentObject();
$this->updateNodePriority();
$this->contentObject->store();
$this->publish();
$this->updateNodePriority();
ezContentObject::clearCache($this->contentObject->attribute('id'));
eZContentCacheManager::clearContentCache($this->contentObject->attribute('id'));
}
protected function prepareAttributeForValue(eZContentObjectAttribute $attribute, $value)
{
$attrDatatype = $attribute->attribute('data_type_string');
switch ($attrDatatype)
{
case 'ezurl':
// NOOP
break;
case 'ezkeyword':
// NOOP
break;
case 'ezdate':
// NOOP
break;
case 'ezdatetime':
// NOOP
break;
case 'ezobjectrelation':
// Remove any exisiting value first from ezobjectrelation
$attribute->setAttribute('data_int', 0);
$attribute->store();
break;
case 'ezobjectrelationlist':
// Remove any exisiting value first from ezobjectrelationlist
$content = $attribute->content();
$relationList =& $content['relation_list'];
$newRelationList = array();
for ($i = 0; $i < count($relationList); ++$i )
{
$relationItem = $relationList[$i];
eZObjectRelationListType::removeRelationObject(
$attribute,
$relationItem
);
}
$content['relation_list'] =& $newRelationList;
$attribute->setContent($content);
$attribute->store();
break;
}
return $attribute;
}
protected function prepareValueForAttribute($value, eZContentObjectAttribute $attribute)
{
$attrDatatype = $attribute->attribute('data_type_string');
switch ($attrDatatype)
{
case 'ezxmltext': $parser = new eZSimplifiedXMLInputParser(null);
$document = $parser->process($value);
$value = eZXMLTextType::domString($document);
break;
case 'ezurl':
// NOOP
break;
case 'ezkeyword':
$keyword = new eZKeyword();
$keyword->initializeKeyword($value);
$value = $keyword;
break;
case 'ezdate':
$value = strtotime($value);
break;
case 'ezdatetime':
$value = strtotime($value);
break;
}
return $value;
}
public function publish()
{
if ($this->contentObject && $this->contentObjectVersion)
{
return eZOperationHandler::execute(
'content',
'publish',
array(
'object_id' => $this->contentObject->attribute('id'),
'version' => $this->contentObjectVersion->attribute('version'),
'user_id' => $this->getUserId(),
)
);
}
trigger_error("No eZContentObject and/or eZContentObject version to publish", E_USER_WARNING);
return false;
}
public function remove()
{
if (!$this->contentObject)
{
$this->getContentObject();
$this->getContentObjectVersion();
}
if ($this->contentObject)
{
eZContentCacheManager::clearContentCacheIfNeeded($this->contentObject->attribute('id'));
$this->contentObject->removeThis();
}
}
/**
* Set the priority of the node, used for specifying an arbitrary sort order of content inside a
* container class inside eZ Publish.
*
* @param int $priority the priority by of this node in relation to any other nodes.
* @return void
* @author Kieran Whitbread
**/
public function setNodePriority($priority)
{
if (preg_match(NINJA_PREG_UINT, $priority))
{
$this->nodePriority = $priority;
}
else
{
NinjaError::trigger(__METHOD__." expects parameter one to be an unsigned integer", E_USER_ERROR, 1);
}
}
/**
* The node id of the parent container content object (e.g. a Folder) where the new node will be placed.
*
* @param int $id the Id of the parent node
* @return void
* @author Kieran Whitbread
**/
public function setParentNodeId($id)
{
if (preg_match(NINJA_PREG_UNIT, $id))
{
$this->parentNodeId = $id;
}
else
{
NinjaError::trigger(__METHOD__." expects parameter one to be an unsigned integer", E_USER_ERROR, 1);
}
}
public function setUserId($id)
{
$this->userId = $id;
}
protected function updateNodePriority()
{
$priority = $this->getNodePriority();
if(!is_null($priority) && $this->contentObject)
{
$parentId = $this->getParentNodeId();
$assignedNodes = $this->contentObject->attribute('assigned_nodes');
$db = eZDB::instance();
foreach($assignedNodes as $assignedNode)
{
$parent = $assignedNode->attribute('parent');
if($parent && $parent->attribute('node_id') == $parentId)
{
$db->begin();
$nodeID = $assignedNode->attribute('node_id');
$db->query("UPDATE `ezcontentobject_tree` SET `priority` = $priority WHERE `node_id` = $nodeID");
$assignedNode->updateAndStoreModified();
$db->commit();
}
}
}
}
protected function updateContentObject()
{
$dataMap = $this->contentObjectVersion->attribute('data_map');
$availableAttributes = $this->source->getAvailableAttributes();
foreach ($availableAttributes as $attributeName)
{
$attribute = $dataMap[$attributeName];
if($attribute)
{
$value = $this->source->getAttributeValue($attributeName);
$value = $this->prepareValueForAttribute($value, $attribute);
$attribute = $this->prepareAttributeForValue($attribute, $value);
$this->updateContentObjectAttribute($attribute, $value);
}
else
{
trigger_error("$attributeName does not exist in the content object", E_USER_WARNING);
}
}
}
protected function updateContentObjectAttribute(eZContentObjectAttribute $attribute, $value)
{
// no longer treating everything as a string.
//$attribute->fromString($value);
// Now we try to determine which internal datatype ez publish will be using for this
// attribute.
$attrDatatype = $attribute->attribute('data_type_string');
switch ($attrDatatype)
{
case 'ezboolean':
$attribute->setAttribute('data_int', $value);
break;
case 'ezdate':
$attribute->setAttribute('data_int', $value);
break;
case 'ezdatetime':
$attribute->setAttribute('data_int', $value);
break;
case 'ezimage':
$attribute->fromString($value);
break;
case 'ezinteger':
$attribute->setAttribute('data_int', $value);
break;
case 'ezisbn':
$attribute->setAttribute('data_text', $value);
break;
case 'ezkeyword':
$attribute->fromString($value);
break;
case 'ezobjectrelationlist':
if (is_array($value))
{
$attribute->fromString(implode('-', $value));
}
else
{
$attribute->fromString($value);
}
break;
case 'ezstring':
$attribute->setAttribute('data_text', $value);
break;
case 'ezurl':
$attribute->setAttribute('data_text', $value);
break;
case 'ezxmltext':
$attribute->fromString($value);
break;
default:
$attribute->fromString($value);
break;
}
$attribute->store();
}
}
