Disabling functionality temporarily during migration
Continuing with techniques from the “Acme” project, the location content type had an address field and a geofield, with field_geofield configured to automatically determine latitude and longitude from the associated field_address - a fact I was initially unaware of. Our source data contained latitude and longitude already, which I mapped directly in the migration:
field_geofield:
plugin: geofield_latlon
source:
- latitude
- longitude
However, testing location migrations by repeatedly running the import, I soon started getting messages from Google Maps API that my daily quota had been exceeded, and quickly tracked down the integration with field_address. Clearly, the calls out to Google Maps were both unnecessary and hazardous - how to prevent them? Fortunately, the migration system provides events which fire before and after each migration is executed. So, we subscribe to MigrateEvents::PRE_IMPORT to save the current settings and disable the external call:
public function onMigrationPreImport(MigrateImportEvent $event) {
if ($event->getMigration()->id() == 'location') {
$fields = \Drupal::entityTypeManager()->getStorage('field_config')->loadByProperties(['field_name' => 'field_geofield']);
if ($fields) {
/** @var \Drupal\field\Entity\FieldConfig $field */
if ($field = $fields['node.location.field_geofield']) {
$this->originalSettings = $field->getThirdPartySettings('geocoder_field');
$field->setThirdPartySetting('geocoder_field', 'method', 'none');
$field->save();
}
}
}
}
And we subscribe to MigrateEvents::POST_IMPORT to restore the original settings:
public function onMigrationPostImport(MigrateImportEvent $event) {
if ($event->getMigration()->id() == 'location') {
$fields = \Drupal::entityTypeManager()->getStorage('field_config')->loadByProperties(['field_name' => 'field_geofield']);
if ($fields) {
/** @var \Drupal\field\Entity\FieldConfig $field */
if ($field = $fields['node.location.field_geofield']) {
foreach ($this->originalSettings as $key => $value) {
$field->setThirdPartySetting('geocoder_field', $key, $value);
}
$field->save();
}
}
}
}
The thoughtful reader may note a risk here - what if someone were adding or editing a location node while this were running? The geofield would not be populated from the address field. In this case, this is not a problem - this is a one-time bulk migration (and no one should be making changes on a production website at such a time). In cases involving an ongoing feed where the feed data is used as-is on the Drupal site, it would also not be a problem, although if there were a practice of manually editing imported content there would be some risk.
Use the Twitter thread below to comment on this post: