Skip to content
This repository has been archived by the owner on Sep 23, 2020. It is now read-only.

Commit

Permalink
added recursive restore to allow also versions of children
Browse files Browse the repository at this point in the history
  • Loading branch information
wachterjohannes committed Mar 23, 2017
1 parent a5e591b commit c385e37
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 16 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
CHANGELOG for Sulu Document Manager
===================================

* dev-develop
* FEATURE #107 Added recursive restore to allow also versions of children

* 0.9.1 (2017-03-16)
* ENHANCEMENT #107 Added VersionNotFoundException

Expand Down
77 changes: 61 additions & 16 deletions lib/Subscriber/Behavior/VersionSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -190,12 +190,14 @@ public function applyVersionOperations()
if (!array_key_exists($versionInformation['path'], $nodeVersions)) {
$nodeVersions[$versionInformation['path']] = $versions;
}
$nodeVersions[$versionInformation['path']][] = json_encode([
'locale' => $versionInformation['locale'],
'version' => $version->getName(),
'author' => $versionInformation['author'],
'authored' => date('c'),
]);
$nodeVersions[$versionInformation['path']][] = json_encode(
[
'locale' => $versionInformation['locale'],
'version' => $version->getName(),
'author' => $versionInformation['author'],
'authored' => date('c'),
]
);
}

foreach ($nodes as $path => $node) {
Expand Down Expand Up @@ -226,26 +228,69 @@ public function restoreProperties(RestoreEvent $event)

$node = $event->getNode();

try {
$version = $this->versionManager->getVersionHistory($node->getPath())->getVersion($event->getVersion());

$frozenNode = $version->getFrozenNode();

$this->restoreNode($node, $frozenNode, $contentPropertyPrefix, $systemPropertyPrefix);
} catch (VersionException $exception) {
throw new VersionNotFoundException($event->getDocument(), $event->getVersion());
}
}

/**
* Restore given node with properties given from frozen-node.
* Will be called recursive.
*
* @param NodeInterface $node
* @param NodeInterface $frozenNode
* @param string $contentPropertyPrefix
* @param string $systemPropertyPrefix
*/
private function restoreNode(
NodeInterface $node,
NodeInterface $frozenNode,
$contentPropertyPrefix,
$systemPropertyPrefix
) {
// remove the properties for the given language, so that values being added since the last version are removed
foreach ($node->getProperties() as $property) {
if ($this->isRestoreProperty($property->getName(), $contentPropertyPrefix, $systemPropertyPrefix)) {
$property->remove();
}
}

try {
$version = $this->versionManager->getVersionHistory($node->getPath())->getVersion($event->getVersion());
// set all the properties from the saved version to the node
foreach ($frozenNode->getPropertiesValues() as $name => $value) {
if ($this->isRestoreProperty($name, $contentPropertyPrefix, $systemPropertyPrefix)) {
$node->setProperty($name, $value);
}
}

$frozenNode = $version->getFrozenNode();
/** @var NodeInterface $childNode */
foreach ($frozenNode->getNodes() as $childNode) {
// create new node if it not exists
if (!$node->hasNode($childNode->getName())) {
$newNode = $node->addNode($childNode->getName());
$newNode->setMixins($childNode->getPropertyValueWithDefault('jcr:mixinTypes', []));
}

// set all the properties from the saved version to the node
foreach ($frozenNode->getPropertiesValues() as $name => $value) {
if ($this->isRestoreProperty($name, $contentPropertyPrefix, $systemPropertyPrefix)) {
$node->setProperty($name, $value);
}
$this->restoreNode(
$node->getNode($childNode->getName()),
$childNode,
$contentPropertyPrefix,
$systemPropertyPrefix
);
}

// remove child-nodes which does not exists in frozen-node
foreach ($node->getNodeNames() as $nodeName) {
if ($frozenNode->hasNode($nodeName)) {
continue;
}
} catch (VersionException $exception) {
throw new VersionNotFoundException($event->getDocument(), $event->getVersion());

$node->getNode($nodeName)->remove();
}
}

Expand Down
69 changes: 69 additions & 0 deletions tests/Unit/Subscriber/Behavior/VersionSubscriberTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ public function testRestoreLocalizedProperties()
$property3 = $this->prophesize(PropertyInterface::class);
$property3->getName()->willReturn('jcr:uuid');
$node->getProperties()->willReturn([$property1->reveal(), $property2->reveal(), $property3->reveal()]);
$node->getNodeNames()->willReturn([]);

$property1->remove()->shouldBeCalled();
$property2->remove()->shouldBeCalled();
Expand All @@ -351,6 +352,7 @@ public function testRestoreLocalizedProperties()
$this->propertyEncoder->localizedContentName('', 'de')->willReturn('i18n:de-');
$this->propertyEncoder->localizedSystemName('', 'de')->willReturn('i18n:de-');

$frozenNode->getNodes()->willReturn([]);
$frozenNode->getPropertiesValues()->willReturn([
'i18n:de-test' => 'Title',
'non-translatable-test' => 'Article',
Expand All @@ -372,4 +374,71 @@ public function testRestoreLocalizedProperties()

$this->versionSubscriber->restoreProperties($event->reveal());
}

public function testRestoreChildren()
{
$event = $this->prophesize(RestoreEvent::class);
$document = $this->prophesize(VersionBehavior::class);
$node = $this->prophesize(NodeInterface::class);
$versionHistory = $this->prophesize(VersionHistoryInterface::class);
$version = $this->prophesize(JackalopeVersion::class);
$frozenNode = $this->prophesize(NodeInterface::class);

$node->getPath()->willReturn('/node');
$node->getProperties()->willReturn([]);
$node->hasNode('child1')->willReturn(false);
$node->hasNode('child2')->willReturn(true);
$node->getNodeNames()->willReturn(['child2', 'child3']);

$newChild1Node = $this->prophesize(NodeInterface::class);
$newChild1Node->setMixins(['jcr:referencable'])->shouldBeCalled();
$newChild1Node->getProperties()->willReturn([]);
$newChild1Node->getNodeNames()->willReturn([]);
$node->addNode('child1')->will(
function () use ($node, $newChild1Node) {
$node->getNode('child1')->willReturn($newChild1Node->reveal());
$node->getNodeNames()->willReturn(['child1', 'child2', 'child3']);

return $newChild1Node->reveal();
}
);
$newChild2Node = $this->prophesize(NodeInterface::class);
$newChild2Node->getProperties()->willReturn([]);
$newChild2Node->getNodeNames()->willReturn([]);
$node->getNode('child2')->willReturn($newChild2Node->reveal());

$newChild3Node = $this->prophesize(NodeInterface::class);
$newChild3Node->remove()->shouldBeCalled();
$node->getNode('child3')->willReturn($newChild3Node->reveal());

$this->propertyEncoder->localizedContentName('', 'de')->willReturn('i18n:de-');
$this->propertyEncoder->localizedSystemName('', 'de')->willReturn('i18n:de-');

$child1 = $this->prophesize(NodeInterface::class);
$child1->getName()->willReturn('child1');
$child1->getPropertyValueWithDefault('jcr:mixinTypes', [])->willReturn(['jcr:referencable']);
$child1->getPropertiesValues()->willReturn([]);
$child1->getNodes()->willReturn([]);
$child2 = $this->prophesize(NodeInterface::class);
$child2->getName()->willReturn('child2');
$child2->getPropertiesValues()->willReturn([]);
$child2->getNodes()->willReturn([]);

$frozenNode->getNodes()->willReturn([$child1->reveal(), $child2->reveal()]);
$frozenNode->getPropertiesValues()->willReturn([]);
$frozenNode->hasNode('child1')->willReturn(true);
$frozenNode->hasNode('child2')->willReturn(true);
$frozenNode->hasNode('child3')->willReturn(false);

$event->getDocument()->willReturn($document->reveal());
$event->getNode()->willReturn($node->reveal());
$event->getVersion()->willReturn('1.0');
$event->getLocale()->willReturn('de');

$this->versionManager->getVersionHistory('/node')->willReturn($versionHistory->reveal());
$versionHistory->getVersion('1.0')->willReturn($version->reveal());
$version->getFrozenNode()->willReturn($frozenNode->reveal());

$this->versionSubscriber->restoreProperties($event->reveal());
}
}

0 comments on commit c385e37

Please sign in to comment.