From e0d70b6059593788d90cffe69150077b3cc5130c Mon Sep 17 00:00:00 2001 From: dannylamb Date: Wed, 18 Sep 2019 14:15:03 -0300 Subject: [PATCH] Allowing NodeHasTerm to check for multiple tags using AND logic (#167) --- src/Plugin/Condition/NodeHasTerm.php | 63 ++++++++++++----- tests/src/Functional/NodeHasTermTest.php | 90 ++++++++++++++++++++++++ 2 files changed, 134 insertions(+), 19 deletions(-) create mode 100644 tests/src/Functional/NodeHasTermTest.php diff --git a/src/Plugin/Condition/NodeHasTerm.php b/src/Plugin/Condition/NodeHasTerm.php index 774f6d7e..dae52ad0 100644 --- a/src/Plugin/Condition/NodeHasTerm.php +++ b/src/Plugin/Condition/NodeHasTerm.php @@ -83,11 +83,12 @@ class NodeHasTerm extends ConditionPluginBase implements ContainerFactoryPluginI * {@inheritdoc} */ public function buildConfigurationForm(array $form, FormStateInterface $form_state) { + $default = []; if (isset($this->configuration['uri']) && !empty($this->configuration['uri'])) { - $default = $this->utils->getTermForUri($this->configuration['uri']); - } - else { - $default = NULL; + $uris = explode(',', $this->configuration['uri']); + foreach ($uris as $uri) { + $default[] = $this->utils->getTermForUri($uri); + } } $form['term'] = [ @@ -96,6 +97,7 @@ class NodeHasTerm extends ConditionPluginBase implements ContainerFactoryPluginI '#tags' => TRUE, '#default_value' => $default, '#target_type' => 'taxonomy_term', + '#required' => TRUE, ]; return parent::buildConfigurationForm($form, $form_state); @@ -108,12 +110,18 @@ class NodeHasTerm extends ConditionPluginBase implements ContainerFactoryPluginI // Set URI for term if possible. $this->configuration['uri'] = NULL; $value = $form_state->getValue('term'); + $uris = []; if (!empty($value)) { - $tid = $value[0]['target_id']; - $term = $this->entityTypeManager->getStorage('taxonomy_term')->load($tid); - $uri = $this->utils->getUriForTerm($term); - if ($uri) { - $this->configuration['uri'] = $uri; + foreach ($value as $target) { + $tid = $target['target_id']; + $term = $this->entityTypeManager->getStorage('taxonomy_term')->load($tid); + $uri = $this->utils->getUriForTerm($term); + if ($uri) { + $uris[] = $uri; + } + } + if (!empty($uris)) { + $this->configuration['uri'] = implode(',', $uris); } } parent::submitConfigurationForm($form, $form_state); @@ -144,18 +152,35 @@ class NodeHasTerm extends ConditionPluginBase implements ContainerFactoryPluginI * TRUE if entity has all the specified term(s), otherwise FALSE. */ protected function evaluateEntity(EntityInterface $entity) { - foreach ($entity->referencedEntities() as $referenced_entity) { - if ($referenced_entity->getEntityTypeId() == 'taxonomy_term' && $referenced_entity->hasField(IslandoraUtils::EXTERNAL_URI_FIELD)) { - $field = $referenced_entity->get(IslandoraUtils::EXTERNAL_URI_FIELD); - if (!$field->isEmpty()) { - $link = $field->first()->getValue(); - if ($link['uri'] == $this->configuration['uri']) { - return $this->isNegated() ? FALSE : TRUE; - } - } - } + // Find the terms on the node. + $terms = array_filter($entity->referencedEntities(), function ($entity) { + return $entity->getEntityTypeId() == 'taxonomy_term' && + $entity->hasField(IslandoraUtils::EXTERNAL_URI_FIELD) && + !$entity->get(IslandoraUtils::EXTERNAL_URI_FIELD)->isEmpty(); + }); + + // Get their URIs. + $haystack = array_map(function ($term) { + return $term->get(IslandoraUtils::EXTERNAL_URI_FIELD)->first()->getValue()['uri']; + }, + $terms + ); + + // FALSE if there's no URIs on the node. + if (empty($haystack)) { + return $this->isNegated() ? TRUE : FALSE; + } + + // Get the URIs to look for. It's a required field, so there + // will always be one. + $needles = explode(',', $this->configuration['uri']); + + // TRUE if every needle is in the haystack. + if (count(array_intersect($needles, $haystack)) == count($needles)) { + return $this->isNegated() ? FALSE : TRUE; } + // Otherwise, FALSE. return $this->isNegated() ? TRUE : FALSE; } diff --git a/tests/src/Functional/NodeHasTermTest.php b/tests/src/Functional/NodeHasTermTest.php new file mode 100644 index 00000000..a27cf474 --- /dev/null +++ b/tests/src/Functional/NodeHasTermTest.php @@ -0,0 +1,90 @@ +createImageTag(); + $this->createPreservationMasterTag(); + } + + /** + * @covers \Drupal\islandora\Plugin\Condition\NodeHasTerm + */ + public function testNodeHasTerm() { + + // Create a new node with the tag. + $node = $this->container->get('entity_type.manager')->getStorage('node')->create([ + 'type' => 'test_type', + 'title' => 'Test Node', + 'field_tags' => [$this->imageTerm->id()], + ]); + + // Create and execute the condition. + $condition_manager = $this->container->get('plugin.manager.condition'); + $condition = $condition_manager->createInstance( + 'node_has_term', + [ + 'uri' => 'http://purl.org/coar/resource_type/c_c513', + ] + ); + $condition->setContextValue('node', $node); + $this->assertTrue($condition->execute(), "Condition should pass if node has the term"); + + // Create a new node without the tag. + $node = $this->container->get('entity_type.manager')->getStorage('node')->create([ + 'type' => 'test_type', + 'title' => 'Test Node', + ]); + + $condition->setContextValue('node', $node); + $this->assertFalse($condition->execute(), "Condition should fail if the node does not have any terms"); + + // Create a new node with the wrong tag. + $node = $this->container->get('entity_type.manager')->getStorage('node')->create([ + 'type' => 'test_type', + 'title' => 'Test Node', + 'field_tags' => [$this->preservationMasterTerm->id()], + ]); + + $condition->setContextValue('node', $node); + $this->assertFalse($condition->execute(), "Condition should fail if the node has terms, but not the one we want."); + + // Check for two tags this time. + // Node still only has one. + $condition = $condition_manager->createInstance( + 'node_has_term', + [ + 'uri' => 'http://purl.org/coar/resource_type/c_c513,http://pcdm.org/use#PreservationMasterFile', + ] + ); + $condition->setContextValue('node', $node); + $this->assertFalse($condition->execute(), "Condition should fail if node does not have both terms"); + + // Create a node with both tags. + $node = $this->container->get('entity_type.manager')->getStorage('node')->create([ + 'type' => 'test_type', + 'title' => 'Test Node', + 'field_tags' => [$this->imageTerm->id(), $this->preservationMasterTerm->id()], + ]); + $condition->setContextValue('node', $node); + $this->assertTrue($condition->execute(), "Condition should pass if node has both terms"); + } + +}