-
-
Save brookinsconsulting/293cb183d4c9a691df22 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* @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