Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brookinsconsulting/293cb183d4c9a691df22 to your computer and use it in GitHub Desktop.
Save brookinsconsulting/293cb183d4c9a691df22 to your computer and use it in GitHub Desktop.
<?php
/**
* @author Henning Kvinnesland <henning@keyteq.no>
* @since 02.06.15
*/
namespace Kavli\GenericBundle\Override;
class ContentPackageHandler extends \eZContentObjectPackageHandler
{
const XML_ROOT_TAG = 'content-object-blocks';
// Keep track of ids assigned to the new objects. (old => new)
protected $objectMap = array();
protected $language;
protected function isMultipleFormat(\DomElement $node)
{
return $node->nodeName == 'object-files-list';
}
public function createObjectListNode($options)
{
/** @var \DomElement $node */
$node = parent::createObjectListNode($options);
$this->language = array_pop($options['language_array']);
$blocks = $this->getObjectBlocks();
if (!count($blocks)) {
return $node;
}
return $this->isMultipleFormat($node) ? $this->storeMultipleBlockXml($node, $blocks) : $this->storeSingleBlockXml($node, $blocks);
}
protected function getXmlNodeContents(\DomElement $node)
{
$nodes = array();
/** @var \DomElement $fileNode */
foreach ($node->childNodes as $fileNode) {
// Lets skip the blanks.
if ($fileNode instanceof \DOMText) {
continue;
}
/** @var \DomElement $objectXml */
$objectXml = $this->fetchObjectFromFile($fileNode);
$filename = $fileNode->getAttribute('filename');
$objectId = $objectXml->getAttribute('ezremote:id');
$nodes[$objectId] = compact('filename', 'objectXml');
}
return $nodes;
}
protected function storeMultipleBlockXml(\DomElement $node, $blocks)
{
$nodes = $this->getXmlNodeContents($node);
foreach ($nodes as $objectId => $objectData) {
if (!isset($blocks[$objectId])) {
continue;
}
/** @var \DomElement $objectXml */
$objectXml = $objectData['objectXml'];
$this->storeSingleBlockXml($objectXml, array($objectId => $blocks[$objectId]));
/** @var \eZPackage $package */
$package = $this->Package;
$filePath = $package->path() . '/' . $this->contentObjectDirectory() . '/' . $objectData['filename'];
$package->storeDOM($filePath, $objectXml->ownerDocument);
}
return $node;
}
protected function storeSingleBlockXml(\DomElement $node, $blocks)
{
$dom = $node->ownerDocument;
$packageRoot = $dom->createElement(self::XML_ROOT_TAG);
$dom->appendChild($packageRoot);
$blockRoot = $dom->createElement('blocks');
$packageRoot->appendChild($blockRoot);
foreach ($blocks as $objectId => $blockArray) {
/** @var \eZPageBlock $block */
foreach ($blockArray as $block) {
$blockXml = $block->toXML($dom);
$blockXml->setAttribute('object-id', $objectId);
$blockRoot->appendChild($blockXml);
}
}
$node->appendChild($packageRoot);
return $node;
}
public function install($package, $installType, $parameters, $name, $os, $filename, $subdirectory, $content, &$installParameters, &$installData)
{
$res = parent::install($package, $installType, $parameters, $name, $os, $filename, $subdirectory, $content, $installParameters, $installData);
if (!$res) {
return false;
}
/** @var \DomElement $content */
$root = $content->firstChild;
/** @var \DomElement $root */
if (!$this->isMultipleFormat($root)) {
$this->installBlocks($root);
return true;
}
foreach ($this->getXmlNodeContents($root) as $nodeContent) {
$objectXml = $nodeContent['objectXml'];
$this->installBlocks($objectXml);
}
return true;
}
protected function installBlocks(\DomElement $node)
{
$rootNode = $node->getElementsByTagName(self::XML_ROOT_TAG)->item(0);
if (!$rootNode) {
return false;
}
/** @var \DomElement $rootNode */
$blockRootNode = $rootNode->getElementsByTagName('blocks')->item(0);
if (!$blockRootNode) {
return false;
}
$blocks = array();
/** @var \DomElement $blockRootNode */
foreach ($blockRootNode->getElementsByTagName('block') as $blockXml) {
/** @var \DomElement $blockXml */
$objectId = $blockXml->getAttribute('object-id');
$blockXml->removeAttribute('object-id');
$block = \eZPageBlock::createFromXML($blockXml);
$blocks[$objectId][$block->id()] = $block;
}
foreach ($blocks as $objectId => $blockArray) {
$newId = $this->objectMap[$objectId];
$newlyCreatedObject = \eZContentObject::fetch($newId);
foreach ($this->getEzPageAttributes($newlyCreatedObject) as $attribute) {
foreach ($this->getZones($attribute) as $zone) {
$this->replaceBlocks($zone, $blocks[$objectId]);
}
// Purge updated data to the database.
$ezPageType = new \eZPageType();
$ezPageType->onPublish($attribute, $newlyCreatedObject, $newlyCreatedObject->assignedNodes());
}
}
return true;
}
/**
* @param \eZPageZone $zone
* @param \eZPageBlock[] $source
*/
protected function replaceBlocks(\eZPageZone $zone, $source)
{
$newBlocks = array();
for ($i = 0; $i < $zone->getBlockCount(); $i++) {
$block = $zone->getBlock($i);
/** @var \eZPageBlock $importedBlock */
$importedBlock = $source[$block->id()];
try {
$newBlocks[] = $this->cloneBlock($importedBlock);
}
// Log the event somewhere sensible
catch (\Exception $e) {}
$zone->removeBlock($i);
}
foreach ($newBlocks as $block) {
$zone->addBlock($block);
}
}
protected function cloneBlock(\eZPageBlock $existingBlock)
{
$block = clone $existingBlock;
for ($i = 0; $i < $block->getItemCount(); $i++) {
$item = $block->getItem($i);
if (!isset($this->objectMap[$item->attribute('object_id')])) {
throw new \Exception('Referenced object not included in package.');
}
$newId = $this->objectMap[$item->attribute('object_id')];
$itemObject = \eZContentObject::fetch($newId);
$item->setAttribute('object_id', $itemObject->ID);
$item->setAttribute('node_id', $itemObject->MainNodeID());
}
return $block;
}
protected function getObjectBlocks()
{
$blocks = array();
/** @var \eZContentObject $object */
foreach ($this->ObjectArray as $object) {
foreach ($this->getEzPageAttributes($object) as $attribute) {
foreach ($this->getZones($attribute) as $zone) {
for ($i = 0; $i < $zone->getBlockCount(); $i++) {
$blocks[$object->ID][] = $zone->getBlock($i);
}
}
}
}
return $blocks;
}
/**
* @param \eZContentObject $object
* @return \eZContentObjectAttribute[]
*/
protected function getEzPageAttributes(\eZContentObject $object)
{
$attributes = $object->contentObjectAttributes(true, false, $this->language);
return array_filter($attributes, function(\eZContentObjectAttribute $attribute)
{
return $attribute->DataTypeString == 'ezpage';
});
}
/**
* @param \eZContentObjectAttribute $attribute
* @return \eZPageZone[]
*/
protected function getZones(\eZContentObjectAttribute $attribute)
{
/** @var \eZPage $attributeContents */
$attributeContents = $attribute->content();
$zones = array();
for ($i = 0; $i < $attributeContents->getZoneCount(); $i++) {
$zones[] = $attributeContents->getZone($i);
}
return $zones;
}
/**
* @param \Domelement[] $objectNodes
* @param \Domelement[] $topNodeListNode
* @param array $installParameters
*
* @return bool
*/
public function installContentObjects($objectNodes, $topNodeListNode, &$installParameters)
{
if (isset($installParameters['user_id']))
$userID = $installParameters['user_id'];
else
$userID = \eZUser::currentUserID();
$handlerType = $this->handlerType();
$firstInstalledID = null;
foreach ($objectNodes as $objectNode) {
/** @var \DomElement $realObjectNode */
$realObjectNode = $this->getRealObjectNode($objectNode);
// Cycle until we reach an element where error has occured.
// If action has been choosen, try install this item again, else skip it.
if (isset($installParameters['error']['error_code']) &&
!$this->isErrorElement($realObjectNode->getAttribute('remote_id'), $installParameters)
) {
continue;
}
//we are here, it means we'll try to install some object.
if (!$firstInstalledID) {
$firstInstalledID = $realObjectNode->getAttribute('remote_id');
}
$newObject = \eZContentObject::unserialize($this->Package, $realObjectNode, $installParameters, $userID, $handlerType);
$this->objectMap[$realObjectNode->getAttribute('ezremote:id')] = $newObject->ID;
if (!$newObject) {
return false;
}
if (is_object($newObject)) {
\eZContentObject::clearCache($newObject->attribute('id'));
unset($newObject);
}
unset($realObjectNode);
if (isset($installParameters['error']) && count($installParameters['error'])) {
$installParameters['error'] = array();
}
}
$this->installSuspendedNodeAssignment($installParameters);
$this->installSuspendedObjectRelations($installParameters);
// Call postUnserialize on all installed objects
foreach ($objectNodes as $objectNode) {
if ($objectNode->localName == 'object') {
$remoteID = $objectNode->getAttribute('remote_id');
} else {
$remoteID = substr($objectNode->getAttribute('filename'), 7, 32);
}
// Begin from the object that we started from in the previous cycle
if ($firstInstalledID && $remoteID != $firstInstalledID) {
continue;
} else {
$firstInstalledID = null;
}
$object = \eZContentObject::fetchByRemoteID($remoteID);
if (is_object($object)) {
$object->postUnserialize($this->Package);
\eZContentObject::clearCache($object->attribute('id'));
}
unset($object);
}
return true;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment