Skip to content

Commit

Permalink
Merge pull request #745 from dannylamb/node-has-term-or
Browse files Browse the repository at this point in the history
Adding OR logic to NodeHasTerm and ilk
  • Loading branch information
mjordan authored Jan 3, 2020
2 parents 732448a + 93a84c6 commit 655f501
Show file tree
Hide file tree
Showing 7 changed files with 262 additions and 23 deletions.
9 changes: 9 additions & 0 deletions config/schema/islandora.schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ condition.plugin.node_has_term:
uri:
type: text
label: 'Taxonomy Term URI'
logic:
type: string
label: 'Logic (AND or OR)'

condition.plugin.node_has_parent:
type: condition.plugin
Expand All @@ -95,13 +98,19 @@ condition.plugin.media_has_term:
uri:
type: text
label: 'Taxonomy Term URI'
logic:
type: string
label: 'Logic (AND or OR)'

condition.plugin.parent_node_has_term:
type: condition.plugin
mapping:
uri:
type: text
label: 'Taxonomy Term URI'
logic:
type: string
label: 'Logic (AND or OR)'

condition.plugin.file_uses_filesystem:
type: condition.plugin
Expand Down
57 changes: 50 additions & 7 deletions src/IslandoraUtils.php
Original file line number Diff line number Diff line change
Expand Up @@ -235,12 +235,32 @@ function ($field) {
* Calling getStorage() throws if the storage handler couldn't be loaded.
*/
public function getTermForUri($uri) {
$results = $this->entityQuery->get('taxonomy_term')
->condition(self::EXTERNAL_URI_FIELD . '.uri', $uri)
// Get authority link fields to search.
$field_map = $this->entityFieldManager->getFieldMap();
$fields = [];
foreach ($field_map['taxonomy_term'] as $field_name => $field_data) {
if ($field_data['type'] == 'authority_link') {
$fields[] = $field_name;
}
}
// Add field_external_uri.
$fields[] = self::EXTERNAL_URI_FIELD;

$query = $this->entityQuery->get('taxonomy_term');

$orGroup = $query->orConditionGroup();
foreach ($fields as $field) {
$orGroup->condition("$field.uri", $uri);
}

$results = $query
->condition($orGroup)
->execute();

if (empty($results)) {
return NULL;
}

return $this->entityTypeManager->getStorage('taxonomy_term')->load(reset($results));
}

Expand All @@ -258,16 +278,39 @@ public function getTermForUri($uri) {
* be created.
*/
public function getUriForTerm(TermInterface $term) {
if ($term && $term->hasField(self::EXTERNAL_URI_FIELD)) {
$field = $term->get(self::EXTERNAL_URI_FIELD);
if (!$field->isEmpty()) {
$link = $field->first()->getValue();
return $link['uri'];
$fields = $this->getUriFieldNamesForTerms();
foreach ($fields as $field_name) {
if ($term && $term->hasField($field_name)) {
$field = $term->get($field_name);
if (!$field->isEmpty()) {
$link = $field->first()->getValue();
return $link['uri'];
}
}
}
return NULL;
}

/**
* Gets every field name that might contain an external uri for a term.
*
* @return string[]
* Field names for fields that a term may have as an external uri.
*/
public function getUriFieldNamesForTerms() {
// Get authority link fields to search.
$field_map = $this->entityFieldManager->getFieldMap();
$fields = [];
foreach ($field_map['taxonomy_term'] as $field_name => $field_data) {
if ($field_data['type'] == 'authority_link') {
$fields[] = $field_name;
}
}
// Add field_external_uri.
$fields[] = self::EXTERNAL_URI_FIELD;
return $fields;
}

/**
* Executes context reactions for a Node.
*
Expand Down
2 changes: 1 addition & 1 deletion src/Plugin/Condition/MediaHasTerm.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*
* @Condition(
* id = "media_has_term",
* label = @Translation("Media has term"),
* label = @Translation("Media has term with URI"),
* context = {
* "media" = @ContextDefinition("entity:media", required = TRUE , label = @Translation("media"))
* }
Expand Down
64 changes: 52 additions & 12 deletions src/Plugin/Condition/NodeHasTerm.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*
* @Condition(
* id = "node_has_term",
* label = @Translation("Node has term"),
* label = @Translation("Node has term with URI"),
* context = {
* "node" = @ContextDefinition("entity:node", required = TRUE , label = @Translation("node"))
* }
Expand Down Expand Up @@ -79,6 +79,16 @@ public static function create(ContainerInterface $container, array $configuratio
);
}

/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return array_merge(
['logic' => 'and'],
parent::defaultConfiguration()
);
}

/**
* {@inheritdoc}
*/
Expand All @@ -94,12 +104,24 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
$form['term'] = [
'#type' => 'entity_autocomplete',
'#title' => $this->t('Term'),
'#description' => $this->t('Only terms that have external URIs/URLs will appear here.'),
'#tags' => TRUE,
'#default_value' => $default,
'#target_type' => 'taxonomy_term',
'#required' => TRUE,
'#selection_handler' => 'islandora:external_uri',
];

$form['logic'] = [
'#type' => 'radios',
'#title' => $this->t('Logic'),
'#description' => $this->t('Whether to use AND or OR logic to evaluate multiple terms'),
'#options' => [
'and' => 'And',
'or' => 'Or',
],
'#default_value' => $this->configuration['logic'],
];
return parent::buildConfigurationForm($form, $form_state);
}

Expand All @@ -124,6 +146,9 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s
$this->configuration['uri'] = implode(',', $uris);
}
}

$this->configuration['logic'] = $form_state->getValue('logic');

parent::submitConfigurationForm($form, $form_state);
}

Expand Down Expand Up @@ -153,35 +178,50 @@ public function evaluate() {
*/
protected function evaluateEntity(EntityInterface $entity) {
// 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();
$field_names = $this->utils->getUriFieldNamesForTerms();
$terms = array_filter($entity->referencedEntities(), function ($entity) use ($field_names) {
if ($entity->getEntityTypeId() != 'taxonomy_term') {
return FALSE;
}

foreach ($field_names as $field_name) {
if ($entity->hasField($field_name) && !$entity->get($field_name)->isEmpty()) {
return TRUE;
}
}
return FALSE;
});

// Get their URIs.
$haystack = array_map(function ($term) {
return $term->get(IslandoraUtils::EXTERNAL_URI_FIELD)->first()->getValue()['uri'];
return $this->utils->getUriForTerm($term);
},
$terms
);

// FALSE if there's no URIs on the node.
if (empty($haystack)) {
return $this->isNegated() ? TRUE : FALSE;
return 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;
if ($this->configuration['logic'] == 'and') {
if (count(array_intersect($needles, $haystack)) == count($needles)) {
return TRUE;
}
return FALSE;
}
// TRUE if any needle is in the haystack.
else {
if (count(array_intersect($needles, $haystack)) > 0) {
return TRUE;
}
return FALSE;
}

// Otherwise, FALSE.
return $this->isNegated() ? TRUE : FALSE;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/Plugin/Condition/ParentNodeHasTerm.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*
* @Condition(
* id = "parent_node_has_term",
* label = @Translation("Parent node for media has term"),
* label = @Translation("Parent node for media has term with URI"),
* context = {
* "media" = @ContextDefinition("entity:media", required = TRUE , label = @Translation("media"))
* }
Expand Down
125 changes: 125 additions & 0 deletions src/Plugin/EntityReferenceSelection/ExternalUriSelection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
<?php

namespace Drupal\islandora\Plugin\EntityReferenceSelection;

use Drupal\taxonomy\Plugin\EntityReferenceSelection\TermSelection;
use Drupal\islandora\IslandoraUtils;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityRepositoryInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Session\AccountInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
* Filters by looking for entities with Authority Links or External Uris.
*
* @EntityReferenceSelection(
* id = "islandora:external_uri",
* label = @Translation("Taxonomy Term with external URI selection"),
* entity_types = {"taxonomy_term"},
* group = "islandora",
* weight = 1
* )
*/
class ExternalUriSelection extends TermSelection {

/**
* Islandora utils.
*
* @var \Drupal\islandora\IslandoraUtils
*/
protected $utils;

/**
* Constructs a new ExternalUriSelection object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity manager service.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler service.
* @param \Drupal\Core\Session\AccountInterface $current_user
* The current user.
* @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager
* The entity field manager.
* @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
* The entity type bundle info service.
* @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
* The entity repository.
* @param \Drupal\islandora\IslandoraUtils $utils
* Islandora utils.
*/
public function __construct(
array $configuration,
$plugin_id,
$plugin_definition,
EntityTypeManagerInterface $entity_type_manager,
ModuleHandlerInterface $module_handler,
AccountInterface $current_user,
EntityFieldManagerInterface $entity_field_manager = NULL,
EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL,
EntityRepositoryInterface $entity_repository = NULL,
IslandoraUtils $utils
) {
parent::__construct(
$configuration,
$plugin_id,
$plugin_definition,
$entity_type_manager,
$module_handler,
$current_user,
$entity_field_manager,
$entity_type_bundle_info,
$entity_repository
);
$this->utils = $utils;
}

/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('entity_type.manager'),
$container->get('module_handler'),
$container->get('current_user'),
$container->get('entity_field.manager'),
$container->get('entity_type.bundle.info'),
$container->get('entity.repository'),
$container->get('islandora.utils')
);
}

/**
* {@inheritdoc}
*/
public function getReferenceableEntities($match = NULL, $match_operator = 'CONTAINS', $limit = 0) {
$options = parent::getReferenceableEntities($match, $match_operator, $limit);

foreach (array_keys($options) as $vid) {
foreach (array_keys($options[$vid]) as $tid) {
$term = $this->entityTypeManager->getStorage('taxonomy_term')->load($tid);
$uri = $this->utils->getUriForTerm($term);
if (empty($uri)) {
unset($options[$vid][$tid]);
}
}
if (empty($options[$vid])) {
unset($options[$vid]);
}
}

return $options;
}

}
Loading

0 comments on commit 655f501

Please sign in to comment.