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: