From f496224086604dd1d1ae54562a901b1b17c5755a Mon Sep 17 00:00:00 2001 From: Jordan Dukart Date: Wed, 30 Mar 2022 11:42:38 -0300 Subject: [PATCH] Add ancestor condition. --- src/Plugin/Condition/NodeHasAncestor.php | 198 +++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 src/Plugin/Condition/NodeHasAncestor.php diff --git a/src/Plugin/Condition/NodeHasAncestor.php b/src/Plugin/Condition/NodeHasAncestor.php new file mode 100644 index 00000000..cc4c207c --- /dev/null +++ b/src/Plugin/Condition/NodeHasAncestor.php @@ -0,0 +1,198 @@ +entityTypeManager = $entity_type_manager; + } + + /** + * {@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'), + ); + } + + /** + * {@inheritdoc} + */ + public function defaultConfiguration(): array { + return parent::defaultConfiguration() + [ + 'ancestor_nids' => FALSE, + 'parent_reference_field' => IslandoraUtils::MEMBER_OF_FIELD, + ]; + } + + /** + * {@inheritdoc} + */ + public function buildConfigurationForm(array $form, FormStateInterface $form_state) { + $default_nids = FALSE; + if ($this->configuration['ancestor_nids']) { + $default_nids = array_map(function ($nid) { + return $this->entityTypeManager->getStorage('node')->load($nid); + }, $this->configuration['ancestor_nids']); + } + $form['ancestor_nids'] = [ + '#type' => 'entity_autocomplete', + '#title' => $this->t('Parent node(s)'), + '#default_value' => $default_nids, + '#required' => TRUE, + '#description' => $this->t("Can be a collection node, compound object or paged content. Accepts multiple values separated by a comma."), + '#target_type' => 'node', + '#tags' => TRUE, + ]; + + $options = []; + $reference_fields = $this->entityTypeManager->getStorage('field_storage_config')->loadByProperties([ + 'type' => 'entity_reference', + 'settings' => [ + 'target_type' => 'node', + ], + ]); + foreach ($reference_fields as $field) { + $options[$field->get('field_name')] = $field->get('field_name'); + } + $form['parent_reference_field'] = [ + '#type' => 'select', + '#title' => $this->t('Direct parent reference'), + '#options' => $options, + '#default_value' => $this->configuration['parent_reference_field'], + '#required' => TRUE, + '#description' => $this->t('Field that contains the reference to its parent node.'), + ]; + + return parent::buildConfigurationForm($form, $form_state); + } + + /** + * {@inheritdoc} + */ + public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { + // Entity autocomplete store things with target IDs, for convenience just + // store the plain nid. + $this->configuration['ancestor_nids'] = array_map(function ($nid) { + return $nid['target_id']; + }, $form_state->getValue('ancestor_nids')); + $this->configuration['parent_reference_field'] = $form_state->getValue('parent_reference_field'); + parent::submitConfigurationForm($form, $form_state); + } + + /** + * {@inheritdoc} + */ + public function evaluate() { + if (empty($this->configuration['ancestor_nids']) && !$this->isNegated()) { + return TRUE; + } + + $node = $this->getContextValue('node'); + if (!$node) { + return FALSE; + } + + $ancestors = []; + $this->findAncestors($node, $ancestors); + return !empty(array_intersect($this->configuration['ancestor_nids'], $ancestors)); + } + + /** + * Recursively finds ancestors of an entity. + * + * @param \Drupal\Core\Entity\ContentEntityInterface $entity + * The entity being checked. + * @param array $ancestors + * The array of ancestors, passed by reference. + */ + protected function findAncestors(ContentEntityInterface $entity, array &$ancestors): void { + $parents = $this->getParents($entity); + foreach ($parents as $parent) { + if (!isset($ancestors[$parent->id()])) { + $ancestors[$parent->id()] = $parent->id(); + $this->findAncestors($parent, $ancestors); + } + } + } + + /** + * Helper that gets the immediate parents of a node. + * + * @param \Drupal\Core\Entity\ContentEntityInterface $entity + * The entity being checked. + * + * @return array + * An array of entity objects keyed by field item deltas. + */ + protected function getParents(ContentEntityInterface $entity): array { + if ($entity->hasField($this->configuration['parent_reference_field'])) { + $field = $entity->get($this->configuration['parent_reference_field']); + if (!$field->isEmpty()) { + return $field->referencedEntities(); + } + } + return []; + } + + /** + * {@inheritdoc} + */ + public function summary() { + if (!empty($this->configuration['negate'])) { + return $this->t('The node does not have node @nid as one of its ancestors.', ['@nid' => $this->configuration['ancestor_nids']]); + } + else { + return $this->t('The node has node @nid as one of its ancestors.', ['@nid' => $this->configuration['ancestor_nids']]); + } + } + +}