1

Trying to copy data from field A (plain text field) to field B (entity reference field with taxonomy) within the same content type. The taxonomy terms used in field B are the same terms used in old field (field A).

Below is my first attempt in writing a hook for field copy (using hook_update_N) but its not working.

function mymodule_update_8001() {
   $node_type = "test_content_type"; 
   $nidArray = db_query("SELECT nid FROM node WHERE type = '%s' ", $node_type);

  foreach ($nidArray as $nid) {
    $node = node_load($nid);
    $termString = $node->field_a;
    $termObject = taxonomy_term_load_multiple_by_name($termString);
    $node->field_b->target_id = $termObject->tid;
    $node->revision = TRUE;
    node_save($node);
  }
}

Any help on this would be greatly appreciated.

0
3

The code doesn't work because it uses node_save(), which is a function Drupal 8 doesn't implement. (If you click on Same name and namespace in other branches on the documentation page, you will notice there isn't a link for any Drupal 8.x version.)
In Drupal 8, where a $node is an instance of a class implementing EntityInterface, a node is saved with $node->save().

The code is also using functions that are still implemented by Drupal 8, but they are deprecated and they will be removed on Drupal 9 or future Drupal versions.

The hook to implement isn't hook_update_N(). As the documentation for that hook says, loading, saving, or performing any other CRUD operation on an entity is never safe to do inside hook_update_N().
The correct hook to implement in this case is hook_post_update_NAME(), which receives the same arguments hook_update_N() gets. The expected return values are the same values expected from hook_update_N().

Since updating all the nodes could possibly cause PHP to time out, depending on the number of nodes the site has, the operation needs to be executed in batches, using the argument hook_post_update_NAME() gets.

The code I would use is the following one.

// Add the following lines at the begin of the mymodule.post_update.php file,
// where this hook is expected to be.
// (Replace mymodule with the machine name of the module you are using to
// implement the hook, in the hook name and in the name of the file containing
// it.) 
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\node\NodeInterface;
use Drupal\taxonomy\TermInterface;

function mymodule_post_update_update_taxonomy_references(&$sandbox) {
  $content_type = 'test_content_type';
  /** @var \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager */
  $entity_type_manager = \Drupal::entityTypeManager(); 
  /** @var \Drupal\Core\Entity\EntityStorageInterface $node_storage */
  $node_storage = $entity_type_manager->getStorage('node');
  /** @var \Drupal\Core\Entity\EntityStorageInterface $taxonomy_term_storage */
  $taxonomy_term_storage = $entity_type_manager->getStorage('taxonomy_term');
  if (!isset($sandbox['total']) && !isset($sandbox['count'])) {
    $sandbox['current'] = 0;
    $sandbox['count'] = 0;
    $sandbox['max'] = array_shift($node_storage->getQuery()
      ->accessCheck(FALSE)
      ->sort('created', 'DESC') 
      ->pager(10)
      ->execute());
    $sandbox['total'] = $node_storage->getQuery()
      ->accessCheck(FALSE)
      ->condition('type', $content_type)
      ->count()->execute();
  }
  if (!empty($sandbox['total'])) {
    $nids = $node_storage->getQuery()
      ->accessCheck(FALSE)
      ->pager(50)
      ->condition('type', $content_type)
      ->condition('nid', $sandbox['current'], '>')
      ->sort('nid', 'ASC')
      ->execute();
    $nodes = $node_storage->loadMultiple($nids);
    /** @var \Drupal\node\NodeInterface $node */
    foreach ($nodes as $node) {
      $sandbox['current'] = $node->id();
      $sandbox['count']++;
      $taxonomy_terms = $taxonomy_term_storage->loadByProperties(['name' => $node->field_a]);
      if (!empty($taxonomy_terms) && is_array($taxonomy_terms)) {
        /** @var \Drupal\taxonomy\TermInterface $taxonomy_term */
        $taxonomy_term = reset($taxonomy_terms);
        $node->field_b->entity = $taxonomy_term;
        $node->setNewRevision();
        $node->save();
      }
    }
  }
  if (empty($sandbox['total']) || $sandbox['current'] >= $sandbox['max']) {
    $sandbox['#finished'] = 1;
  }
  else {
    $sandbox['#finished'] = $sandbox['count'] / $sandbox['total'];
  } 
}
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.