From 5c38ce1e47c6be3c4297efa63f73d62c3b43c6fa Mon Sep 17 00:00:00 2001 From: Jared Whiklo Date: Tue, 21 Mar 2017 10:35:58 -0500 Subject: [PATCH] Clean up parents on resource deletion (#41) * Add remove fedora_has_parent function Remove fedora_has_parent if the parent is deleted * Coding style * What the WHAT * Change variables to use less node-tastic terminology * Adding tests Fixing setParent type hint Fixing hasParent logic * Coder * Fix parent clean up test. * Coder --- src/Entity/FedoraResource.php | 52 ++++++- src/FedoraResourceInterface.php | 5 +- .../DeleteFedoraResourceWithParentsTest.php | 92 ++++++++++++ tests/src/Kernel/FedoraResourceParentTest.php | 134 ++++++++++++++++++ 4 files changed, 277 insertions(+), 6 deletions(-) create mode 100644 tests/src/Kernel/DeleteFedoraResourceWithParentsTest.php create mode 100644 tests/src/Kernel/FedoraResourceParentTest.php diff --git a/src/Entity/FedoraResource.php b/src/Entity/FedoraResource.php index a9939619..513d4749 100644 --- a/src/Entity/FedoraResource.php +++ b/src/Entity/FedoraResource.php @@ -117,6 +117,28 @@ class FedoraResource extends ContentEntityBase implements FedoraResourceInterfac } } + /** + * {@inheritdoc} + */ + public static function postDelete(EntityStorageInterface $storage, array $entities) { + parent::postDelete($storage, $entities); + + // This removes references to deleted parents. But this could be + // used to remove child entities instead. + foreach ($entities as $entity) { + if ($entity->getEntityType()->getBundleEntityType() == 'fedora_resource_type') { + $references = self::getInboundReferences($entity); + if ($references) { + $ref_entities = $storage->loadMultiple($references); + foreach ($ref_entities as $ref_entity) { + $ref_entity->removeParent(); + $ref_entity->save(); + } + } + } + } + } + /** * {@inheritdoc} */ @@ -203,7 +225,7 @@ class FedoraResource extends ContentEntityBase implements FedoraResourceInterfac * {@inheritdoc} */ public function hasParent() { - return ($this->get('fedora_has_parent')->first() !== NULL); + return (!$this->get('fedora_has_parent')->isEmpty()); } /** @@ -232,11 +254,19 @@ class FedoraResource extends ContentEntityBase implements FedoraResourceInterfac /** * {@inheritdoc} */ - public function setParent(EntityTypeInterface $entity) { + public function setParent(FedoraResourceInterface $entity) { $this->set('fedora_has_parent', $entity); return $this; } + /** + * {@inheritdoc} + */ + public function removeParent() { + $this->set('fedora_has_parent', NULL); + return $this; + } + /** * Default value callback for 'fedora_has_parent' base field definition. * @@ -250,6 +280,22 @@ class FedoraResource extends ContentEntityBase implements FedoraResourceInterfac return NULL; } + /** + * Get all the objects that have $entity as a fedora_has_parent. + * + * @param \Drupal\islandora\FedoraResourceInterface $entity + * The entity to find inbound references for. + * + * @return array + * An array of entity ids + */ + protected static function getInboundReferences(FedoraResourceInterface $entity) { + // TODO: Not use static loading. + $query = \Drupal::entityQuery('fedora_resource'); + $query->condition('fedora_has_parent', $entity->id()); + return $query->execute(); + } + /** * {@inheritdoc} */ @@ -305,7 +351,7 @@ class FedoraResource extends ContentEntityBase implements FedoraResourceInterfac ->setRevisionable(TRUE) ->setSetting('target_type', 'fedora_resource') ->setSetting('handler', 'default') - ->setDefaultValueCallback('Drupal\islandora\Entity\FedoraResource::getFedoraRoot') + ->setDefaultValueCallback('\Drupal\islandora\Entity\FedoraResource::getFedoraRoot') ->setTranslatable(TRUE) ->setDisplayOptions('view', [ 'label' => 'hidden', diff --git a/src/FedoraResourceInterface.php b/src/FedoraResourceInterface.php index 8fe58a8e..c7b472f2 100644 --- a/src/FedoraResourceInterface.php +++ b/src/FedoraResourceInterface.php @@ -4,7 +4,6 @@ namespace Drupal\islandora; use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Entity\EntityChangedInterface; -use Drupal\Core\Entity\EntityTypeInterface; use Drupal\user\EntityOwnerInterface; /** @@ -109,12 +108,12 @@ interface FedoraResourceInterface extends ContentEntityInterface, EntityChangedI /** * Get the parent entity. * - * @param \Drupal\Core\Entity\EntityTypeInterface $entity + * @param \Drupal\islandora\FedoraResourceInterface $entity * The parent entity. * * @return \Drupal\islandora\FedoraResourceInterface * The called Fedora resource entity. */ - public function setParent(EntityTypeInterface $entity); + public function setParent(FedoraResourceInterface $entity); } diff --git a/tests/src/Kernel/DeleteFedoraResourceWithParentsTest.php b/tests/src/Kernel/DeleteFedoraResourceWithParentsTest.php new file mode 100644 index 00000000..ea496c29 --- /dev/null +++ b/tests/src/Kernel/DeleteFedoraResourceWithParentsTest.php @@ -0,0 +1,92 @@ +assertTrue($this->checkPermissions($permissions), 'Permissions are invalid'); + + $this->user = $this->createUser($permissions); + + // Create a test entity. + $this->parentEntity = FedoraResource::create([ + "type" => "rdf_source", + "uid" => $this->user->get('uid'), + "name" => "Test Parent", + "langcode" => "und", + "status" => 1, + ]); + $this->parentEntity->save(); + + $this->childEntity = FedoraResource::create([ + "type" => "rdf_source", + "uid" => $this->user->get('uid'), + "name" => "Test Child", + "langcode" => "und", + "fedora_has_parent" => $this->parentEntity, + "status" => 1, + ]); + $this->childEntity->save(); + } + + /** + * Tests cleaning up child to parent references when parent is deleted. + * + * @covers \Drupal\islandora\Entity\FedoraResource::postDelete + */ + public function testCleanUpParents() { + $child_id = $this->childEntity->id(); + // Load the child entity. + $new_child = FedoraResource::load($child_id); + // Verify it has a parent. + $this->assertFalse($new_child->get('fedora_has_parent')->isEmpty(), "Should have a parent."); + // Delete the parent entity. + $this->parentEntity->delete(); + // Verify we don't have a parent anymore. + $this->assertTrue($new_child->get('fedora_has_parent')->isEmpty(), "Should not have a parent."); + + } + +} diff --git a/tests/src/Kernel/FedoraResourceParentTest.php b/tests/src/Kernel/FedoraResourceParentTest.php new file mode 100644 index 00000000..9c8da719 --- /dev/null +++ b/tests/src/Kernel/FedoraResourceParentTest.php @@ -0,0 +1,134 @@ +assertTrue($this->checkPermissions($permissions), 'Permissions are invalid'); + + $this->user = $this->createUser($permissions); + + $this->entity = FedoraResource::create([ + 'type' => 'rdf_source', + 'uid' => $this->user->get('uid'), + 'name' => 'Test Entity', + 'langcode' => 'und', + 'status' => 1, + ]); + $this->entity->save(); + + $this->parentEntity = FedoraResource::create([ + 'type' => 'rdf_source', + 'uid' => $this->user->get('uid'), + 'name' => 'Parent Entity', + 'langcode' => 'und', + 'status' => 1, + ]); + $this->parentEntity->save(); + } + + /** + * @covers \Drupal\islandora\Entity\FedoraResource::setParent + */ + public function testSetParent() { + $this->assertTrue($this->entity->get('fedora_has_parent')->isEmpty(), "Entity has an unexpected parent."); + + $this->entity->setParent($this->parentEntity); + $this->entity->save(); + + $this->assertFalse($this->entity->get('fedora_has_parent')->isEmpty(), "Entity has no parent."); + } + + /** + * @covers \Drupal\islandora\Entity\FedoraResource::removeParent + */ + public function testRemoveParent() { + $this->assertTrue($this->entity->get('fedora_has_parent')->isEmpty(), "Entity has an unexpected parent."); + + $this->entity->set('fedora_has_parent', $this->parentEntity); + $this->entity->save(); + + $this->assertFalse($this->entity->get('fedora_has_parent')->isEmpty(), "Entity has no parent."); + + $this->entity->removeParent(); + $this->entity->save(); + + $this->assertTrue($this->entity->get('fedora_has_parent')->isEmpty(), "Entity has an unexpected parent."); + } + + /** + * @covers \Drupal\islandora\Entity\FedoraResource::hasParent + */ + public function testHasParent() { + $this->assertTrue($this->entity->get('fedora_has_parent')->isEmpty(), "Entity has an unexpected parent."); + $this->assertFalse($this->entity->hasParent(), "hasParent is reporting a parent incorrectly."); + + $this->entity->set('fedora_has_parent', $this->parentEntity); + $this->entity->save(); + + $this->assertFalse($this->entity->get('fedora_has_parent')->isEmpty(), "Entity has no parent."); + $this->assertTrue($this->entity->hasParent(), "hasParent is reporting NO parent incorrectly."); + + $this->entity->set('fedora_has_parent', NULL); + $this->entity->save(); + + $this->assertTrue($this->entity->get('fedora_has_parent')->isEmpty(), "Entity still has a parent."); + $this->assertFalse($this->entity->hasParent(), "hasParent is reporting a parent incorrectly."); + } + + /** + * @covers \Drupal\islandora\Entity\FedoraResource::getParentId + */ + public function testGetParentId() { + $id = $this->parentEntity->id(); + + $this->entity->set('fedora_has_parent', $this->parentEntity); + $this->entity->save(); + + $this->assertEquals($id, $this->entity->getParentId(), "Did not get correct parent id."); + } + +}