Provide a migrate process plugin to parse text values

Created on 21 December 2021, almost 4 years ago
Updated 11 April 2025, 7 months ago

Problem/Motivation

When migrating values from a text field into a name field, there is no process plugin to parse the components of the name out of the text.

Proposed resolution

A process plugin is provided below.

Remaining tasks

Include this code in the module at name/src/Plugin/migrate/process/NameField.php .

namespace Drupal\name\Plugin\migrate\process;

use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\Row;

/**
 * Parses text values into name values.
 *
 * @MigrateProcessPlugin(
 *   id = "name_field"
 * )
 */
class NameField extends ProcessPluginBase {

  /**
   * {@inheritdoc}
   */
  public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
    // Get rid of any leading or trailing spaces.
    $value = trim($value);
    // Get rid of any duplicate spaces.
    $value = preg_replace('/  +/', ' ', $value);
    $words = explode(' ', $value);
    if (count($words) == 1) {
      // Assume just a credential.
      return ['credentials' => $value];
    }
    
    // Focus on credentials first.
    $paren = strpos($value, '(');
    $close = strpos($value, ')');
    $slash = strpos($value, '/');
    $dash = strpos($value, ' -') ?: strpos($value, '- ');
    $comma = strpos($value, ',');
    $creds = ['Attorney', 'CEO', 'Chef', 'Pastor', 'President'];
    $gen = ['Jr.', 'II', 'III', 'IV', 'V'];
    $parsed = [];
    if ($paren && $close > $paren) {
      // Assume credentials are in the parentheses.
      $parsed['credentials'] = trim(substr($value, $paren + 1, $close - $paren - 1));
      $value = substr($value, 0, $paren);
    }
    elseif ($comma && $slash > $comma) {
      // Assume credentials follow the comma and contain a slash.
      $parsed['credentials'] = trim(substr($value, $comma + 1));
      $value = substr($value, 0, $comma);
    }
    elseif (in_array(trim($words[0]), $creds)) {
      // First word is credential.
      $parsed['credentials'] = trim(array_shift($words));
      $value = substr($value, strpos($value, ' '));
    }
    elseif ($slash) {
      // Assume credentials follow the slash.
      $parsed['credentials'] = trim(substr($value, $slash + 1));
      $value = substr($value, 0, $slash);
    }
    elseif ($dash) {
      // Assume credentials follow the dash & space.
      $parsed['credentials'] = trim(substr($value, $dash + 2));
      $value = substr($value, 0, $dash);
    }
    elseif ($comma) {
      $after = trim(substr($value, $comma + 1));
      // Check for generational.
      if (in_array($after, $gen)) {
        $parsed['generational'] = $after;
      }
      else {
        // Assume credentials follow the comma.
        $parsed['credentials'] = $after;
      }
      $value = substr($value, 0, $comma);
    }
    elseif (in_array(trim(end($words)), $creds)) {
      // Last word is credential.
      $parsed['credentials'] = array_pop($words);
      $value = substr($value, 0, strrpos($value, ' '));
    }

    // Now that credentials are out of the way, let's look at what's left.
    $words = explode(' ', trim($value, " \t,/()-"));
    $titles = ['Dr.', 'Mr.'];
    if (in_array(trim($words[0]), $titles)) {
      // First word is title.
      $parsed['title'] = trim(array_shift($words));
    }
    if (in_array(trim(end($words)), $gen)) {
      // Final word is generational.
      $parsed['generational'] = trim(array_pop($words));
    }
    // Assume first remaining word is given name.
    $parsed['given'] = trim(array_shift($words));
    if (count($words) > 1) {
      // Assume first remaining word is middle name.
      $parsed['middle'] = trim(array_shift($words));
    }
    // Assume everything remaining is the family name.
    $parsed['family'] = trim(implode(' ', $words));
    
    return $parsed;
  }

}

To use this in a migration:

process:
  field_name:
    plugin: name_field
    source: field_name_text/0/value
✨ Feature request
Status

Needs work

Version

1.0

Component

Code

Created by

πŸ‡ΊπŸ‡ΈUnited States BenStallings

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

Production build 0.71.5 2024