View source
<?php
namespace Drupal\Tests\entity_hierarchy\Kernel;
use Drupal\Core\Entity\EntityInterface;
use PNX\NestedSet\Node;
class HierarchyNestedSetIntegrationTest extends EntityHierarchyKernelTestBase {
public function testNestedSetStorageSimple() {
$child = $this
->createTestEntity($this->parent
->id());
$this
->assertSimpleParentChild($child);
}
public function testNestedSetOrdering() {
$entities = $this
->createChildEntities($this->parent
->id());
$root_node = $this->treeStorage
->getNode($this->parentStub);
$this
->assertChildOrder($root_node, $entities, [
'Child 5',
'Child 4',
'Child 3',
'Child 2',
'Child 1',
]);
$name = 'Child 6';
$entities[$name] = $this
->createTestEntity($this->parent
->id(), $name, -2);
$this
->assertChildOrder($root_node, $entities, [
'Child 5',
'Child 4',
'Child 3',
'Child 2',
'Child 6',
'Child 1',
]);
}
public function testRemoveParentReference() {
$child = $this
->createTestEntity($this->parent
->id());
$root_node = $this->treeStorage
->getNode($this->parentStub);
$this
->assertSimpleParentChild($child);
$child
->set(static::FIELD_NAME, NULL);
$child
->save();
$children = $this
->getChildren($root_node);
$this
->assertCount(0, $children);
$child_node = $this->treeStorage
->getNode($this->nodeFactory
->fromEntity($child));
$this
->assertEquals(0, $child_node
->getDepth());
}
public function testDeleteChild() {
$child = $this
->createTestEntity($this->parent
->id());
$root_node = $this->treeStorage
->getNode($this->parentStub);
$children = $this
->getChildren($root_node);
$this
->assertCount(1, $children);
$child
->delete();
$children = $this
->getChildren($root_node);
$this
->assertCount(0, $children);
}
public function testDeleteParent() {
$child = $this
->createTestEntity($this->parent
->id());
$child2 = $this
->createTestEntity($this->parent
->id());
$this
->createTestEntity($child
->id());
$grandchild2 = $this
->createTestEntity($child2
->id());
$grandchildNodeKey = $this->nodeFactory
->fromEntity($grandchild2);
$grandchild2_node = $this->treeStorage
->getNode($grandchildNodeKey);
$this
->assertEquals(2, $grandchild2_node
->getDepth());
$root_node = $this->treeStorage
->getNode($this->parentStub);
$children = $this
->getChildren($root_node);
$this
->assertCount(2, $children);
$child2
->delete();
$children = $this
->getChildren($root_node);
$this
->assertCount(2, $children);
$reload = function ($id) {
return \Drupal::entityTypeManager()
->getStorage(static::ENTITY_TYPE)
->loadUnchanged($id);
};
$grandchild2 = $reload($grandchild2
->id());
$field_name = static::FIELD_NAME;
$this
->assertNotNull($grandchild2);
$this
->assertEquals($this->parent
->id(), $grandchild2->{$field_name}->target_id);
$grandchildNodeKey = $this->nodeFactory
->fromEntity($grandchild2);
$grandchild2_node = $this->treeStorage
->getNode($grandchildNodeKey);
$this
->assertEquals(1, $grandchild2_node
->getDepth());
$this->parent
->delete();
$grandchild2 = $reload($grandchild2
->id());
$grandchild2_node = $this->treeStorage
->getNode($this->nodeFactory
->fromEntity($grandchild2));
$this
->assertEquals(0, $grandchild2_node
->getDepth());
$grandchild2 = $reload($grandchild2
->id());
$child = $reload($grandchild2
->id());
$this
->assertEquals(NULL, $grandchild2->{self::FIELD_NAME}->target_id);
$this
->assertEquals(NULL, $child->{self::FIELD_NAME}->target_id);
}
public function testDeleteChildWithGrandChildren() {
$child = $this
->createTestEntity($this->parent
->id());
$grand_child = $this
->createTestEntity($child
->id(), 'Grandchild 1', 1);
$this
->assertSimpleParentChild($child);
$this
->assertSimpleParentChild($grand_child, $child, 1);
$child
->delete();
$this
->assertSimpleParentChild($grand_child, $this->parent);
}
public function testRemoveParentReferenceWithGrandChildren() {
$child = $this
->createTestEntity($this->parent
->id());
$grand_child = $this
->createTestEntity($child
->id(), 'Grandchild 1', 1);
$root_node = $this->treeStorage
->getNode($this->parentStub);
$this
->assertSimpleParentChild($child);
$this
->assertSimpleParentChild($grand_child, $child, 1);
$child
->set(static::FIELD_NAME, NULL);
$child
->save();
$children = $this
->getChildren($root_node);
$this
->assertCount(0, $children);
$this
->assertSimpleParentChild($grand_child, $child);
}
public function testNestedSetStorageSimpleUpdate() {
$child = $this
->createTestEntity($this->parent
->id());
$this
->assertSimpleParentChild($child);
$child
->save();
$this
->assertSimpleParentChild($child);
}
public function testNestedSetStorageWithSiblingUpdate() {
$child = $this
->createTestEntity($this->parent
->id(), 'Child 1', 1);
$sibling = $this
->createTestEntity($this->parent
->id(), 'Child 2', 2);
$this
->assertParentWithTwoChildren($child, $sibling);
$child
->save();
$this
->assertParentWithTwoChildren($child, $sibling);
}
public function testNestedSetStorageMoveParent() {
$child = $this
->createTestEntity($this->parent
->id(), 'Child 1', 1);
$parent2 = $this
->createTestEntity(NULL, 'Parent 2');
$parent2
->save();
$this
->assertSimpleParentChild($child);
$child
->set(static::FIELD_NAME, $parent2
->id());
$child
->save();
$this
->assertSimpleParentChild($child, $parent2);
}
public function testNestedSetStorageMoveParentWithChildren() {
$child = $this
->createTestEntity($this->parent
->id(), 'Child 1', 1);
$parent2 = $this
->createTestEntity(NULL, 'Parent 2');
$grandchild = $this
->createTestEntity($child
->id(), 'Grandchild 1', 1);
$this
->assertSimpleParentChild($child);
$this
->assertSimpleParentChild($grandchild, $child, 1);
$child
->set(static::FIELD_NAME, $parent2
->id());
$child
->save();
$this
->assertSimpleParentChild($child, $parent2);
$this
->assertSimpleParentChild($grandchild, $child, 1);
}
public function testNestedSetStorageMoveParentWithSiblingOrdering() {
$child = $this
->createTestEntity($this->parent
->id(), 'Cousin 1', -2);
$parent2 = $this
->createTestEntity(NULL, 'Parent 2');
$child_entities = $this
->createChildEntities($parent2
->id(), 5);
$child_entities['Cousin 1'] = $child;
$this
->assertSimpleParentChild($child);
$child
->set(static::FIELD_NAME, $parent2
->id());
$child
->save();
$this
->assertChildOrder($this->treeStorage
->getNode($this->nodeFactory
->fromEntity($parent2)), $child_entities, [
'Child 5',
'Child 4',
'Child 3',
'Child 2',
'Cousin 1',
'Child 1',
]);
}
public function testNestedSetParentToChild() {
$child = $this
->createTestEntity(NULL);
$child
->set(static::FIELD_NAME, $this->parent
->id());
$child
->save();
$this
->assertSimpleParentChild($child);
}
public function testNestedSetParentToChildWithSiblings() {
$child = $this
->createTestEntity(NULL, 'Once was a parent');
$entities = $this
->createChildEntities($this->parent
->id());
$entities[$child
->label()] = $child;
$child->{static::FIELD_NAME} = [
'target_id' => $this->parent
->id(),
'weight' => -2,
];
$child
->save();
$this
->assertChildOrder($this->treeStorage
->getNode($this->parentStub), $entities, [
'Child 5',
'Child 4',
'Child 3',
'Child 2',
'Once was a parent',
'Child 1',
]);
}
public function testNestedSetResaveParent() {
$entities = $this
->createChildEntities($this->parent
->id());
$root_node = $this->treeStorage
->getNode($this->parentStub);
$this
->assertChildOrder($root_node, $entities, [
'Child 5',
'Child 4',
'Child 3',
'Child 2',
'Child 1',
]);
$name = 'Child 6';
$entities[$name] = $this
->createTestEntity($this->parent
->id(), $name, -2);
$this
->assertChildOrder($root_node, $entities, [
'Child 5',
'Child 4',
'Child 3',
'Child 2',
'Child 6',
'Child 1',
]);
$this
->resaveParent();
$this
->assertChildOrder($this->treeStorage
->getNode($this->parentStub), $entities, [
'Child 5',
'Child 4',
'Child 3',
'Child 2',
'Child 6',
'Child 1',
]);
}
protected function resaveParent() {
$this->parent
->save();
$this->parentStub = $this->nodeFactory
->fromEntity($this->parent);
}
protected function assertSimpleParentChild(EntityInterface $child, EntityInterface $parent = NULL, $baseDepth = 0) {
$parent = $parent ?: $this->parent;
$root_node = $this->treeStorage
->getNode($this->nodeFactory
->fromEntity($parent));
$this
->assertNotEmpty($root_node);
$this
->assertEquals($parent
->id(), $root_node
->getId());
$this
->assertEquals($this
->getEntityRevisionId($parent), $root_node
->getRevisionId());
$this
->assertEquals(0 + $baseDepth, $root_node
->getDepth());
$children = $this
->getChildren($root_node);
$this
->assertCount(1, $children);
$first = reset($children);
$this
->assertEquals($child
->id(), $first
->getId());
$this
->assertEquals($this
->getEntityRevisionId($child), $first
->getRevisionId());
$this
->assertEquals(1 + $baseDepth, $first
->getDepth());
}
protected function assertParentWithTwoChildren(EntityInterface $child, EntityInterface $sibling) {
$root_node = $this->treeStorage
->getNode($this->parentStub);
$this
->assertNotEmpty($root_node);
$this
->assertEquals($this->parent
->id(), $root_node
->getId());
$this
->assertEquals($this
->getEntityRevisionId($this->parent), $root_node
->getRevisionId());
$this
->assertEquals(0, $root_node
->getDepth());
$children = $this
->getChildren($root_node);
$this
->assertCount(2, $children);
$first = reset($children);
$this
->assertEquals($child
->id(), $first
->getId());
$this
->assertEquals($this
->getEntityRevisionId($child), $first
->getRevisionId());
$this
->assertEquals(1, $first
->getDepth());
$last = end($children);
$this
->assertEquals($sibling
->id(), $last
->getId());
$this
->assertEquals($this
->getEntityRevisionId($sibling), $last
->getRevisionId());
$this
->assertEquals(1, $last
->getDepth());
}
protected function getEntityRevisionId(EntityInterface $entity) {
$id = $entity
->id();
if (!($revision_id = $entity
->getRevisionId())) {
$revision_id = $id;
}
return $revision_id;
}
protected function getChildren(Node $parent_node) {
return $this->treeStorage
->findChildren($parent_node
->getNodeKey());
}
protected function assertChildOrder(Node $parent_node, array $entities, array $order) {
$children = $this
->getChildren($parent_node);
$this
->assertCount(count($order), $children);
$this
->assertEquals(array_map(function ($name) use ($entities) {
return $entities[$name]
->id();
}, $order), array_map(function (Node $node) {
return $node
->getId();
}, $children));
return $children;
}
}