Score:0

Populate field value based on external API response

gh flag

My custom Drupal 10 module takes the value of an address field submitted by the user during node creation, sends that to an external API, and then fills a taxonomy term reference field based on the decoded JSON response and logic that matches to the corresponding term. (Might add more fields and potentially APIs in the future).

I have this working but encountered an issue in that because this implements "hook_node_presave", the code is not executed when previewing a node. I'm fairly new to building modules in Drupal so I am now questioning whether there is a better approach to fill this need. Is there an easy fix for this or do I need to re-architect the module? A consideration that comes to mind is perhaps the API call should be triggered from the node edit page - meaning provide the user a button to click and then give a success/failure notice but I am not sure where to begin.

Any guidance is truly appreciated!

Here is the code for the function in question, in case that's helpful:

function neighborhood_taxonomy_node_presave($node) {
  // Check if the node has an address.
  if (isset($node->field_address) && $node->field_address instanceof FieldItemListInterface) {
    // Get the address value from the node.
    $address = $node->get('field_address')->getString();

    // Get the current value of the neighborhood field.
    $currentNeighborhood = $node->field_neighborhood->target_id;

    // Bypass API call if we are updating the node without changing the address or reverting the node to a prior revision.
    $isUpdatedNode = !$node->isNew() && $node->original && $address === $node->original->get('field_address')->getString() && !empty($currentNeighborhood);
    $reverted = $node->original && $node->original->isDefaultRevision() && !$node->isDefaultRevision();

    if ($isUpdatedNode || $reverted) {
      \Drupal::logger('neighborhood_taxonomy')->info('Bypassing API call for node @nid.', [
        '@nid' => $node->id(),
      ]);
      return;
    }

    // Retrieve the neighborhood from the API
    $neighborhoodData = getNeighborhood($address);

    if ($neighborhoodData !== false) {
      $neighborhood = $neighborhoodData['neighborhood'];

      // Get all term in the Neighborhoods vocabulary.
      $vid = 'neighborhoods';
      $query = \Drupal::entityQuery('taxonomy_term');
      $query->condition('vid', $vid);
      // Add an access check to the entity query.
      $query->accessCheck(TRUE);
      $tids = $query->execute();

      // Load all the terms and their field_neighborhood_id values.
      $terms = \Drupal\taxonomy\Entity\Term::loadMultiple($tids);

      $matching_tid = null;

      foreach ($terms as $term) {
        // Load the field_neighborhood_id values for the term.
        $field_neighborhood_id = $term->get('field_neighborhood_id')->getValue();

        // Check for a match based on the neighborhood ID.
        $matching_values = array_column($field_neighborhood_id, 'value');
        if (in_array($neighborhood['id'], $matching_values)) {
          $matching_tid = $term->id();
          break;
        }

        // Check for a match based on neighborhood name.
        $term_name = $term->getName();
        if (strcasecmp($neighborhood['text'], $term_name) === 0) {
          $matching_tid = $term->id();
          break;
        }
      }

      $node->field_neighborhood->target_id = $matching_tid;

      // Log the neighborhood retrieval event.
      \Drupal::logger('neighborhood_taxonomy')->info('Set term for node @nid: @term', [
        '@nid' => $node->id(),
        '@term' => $term->getName(),
      ]);
    }
  }
}
id flag
It seems you may prefer to use Drupal’s AJAX API for this.
twhitefrd avatar
gh flag
@cilefen thank you for your response. I am looking into that and hopefully I'll be able to make this work.
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.