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
Comments
Comment #2
liam morlandPlease put these changes into an issue fork and merge request.
Comment #3
tyapchyc commentedComment #5
tyapchyc commentedComment #8
bluegeek9 commentedThe plugin needs tests.
It would be better if values were not hard coded. I am open to suggestions. I guess it could use the values in the field instance of the destination.
It appears that this plugin is very opinionated on how names will be formatted. Maybe there is away to use a name format as an argument to the plugin?
Comment #9
benstallings commentedComment #10
benstallings commentedHere you go, @bluegeek9!
Comment #11
bluegeek9 commentedIt is hard to tell what the transform method is doing. Can we refactor using protected or private methods?
https://issue.pages.drupalcode.org/-/name-3255533/-/jobs/9378971/artifac...
Comment #12
bluegeek9 commented