Avoid sending emails while doing a migration on Drupal 8
On a migration, Drupal read from an external source the data and create content in our new Drupal Site, and while do that Drupal execute any hook/event related to the new content. So any hook_entity_insert is triggered for every new entity saved on our new site.
This can be a problem if we have some features in our new site which are executed when a new content is created (like send a tweet or send an email) when we run the migration we will have a ton of emails or tweets of the old content and usually, that is not the expected behavior.
Fortunately, in Drupal 8 the migrations are Events and we can create an EventSubscriber (more about EventSubscribers here) which will allow us to create a flag before the migration run so we can determine in our code if the entity has been created in a migration or not.
The main idea was taken from this Moshe Weitzman gist (Thanks!) I will add just the missing parts.
First, we generate all the event subscriber related files using this Drupal Console command:
drupal generate:event:subscriber
The console will ask some question (in which module we want to generate the EventSubscriber and the name of the service)
Enter the module name [config_log]:
> your_module
Enter the service name [simple_faq.default]:
> migration_events.subscriber
Class name [DefaultSubscriber]:
> MigrationEvents
Enter event name [ ]:
>
Do you want to load services from the container (yes/no) [no]:
> no
Do you confirm generation? (yes/no) [yes]:
>yes
This will generate two files:
modules/custom/your_module/your_module.services.yml
Which basically let drupal know that we have a Subscriber there which needs to be executed and:
modules/custom/your_module/src/EventSubscriber/MigrationEvents.php
With this content:
namespace Drupal\simple_faq\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\EventDispatcher\Event;
/**
* Class MigrationEvents.
*
* @package Drupal\simple_faq
*/
class MigrationEvents implements EventSubscriberInterface {
/**
* Constructs a new MigrationEvents object.
*/
public function __construct() {
}
/**
* {@inheritdoc}
*/
static function getSubscribedEvents() {
return $events;
}
}
On this file we need to add our flag which will indicate drupal that we are running the migration. First, we need to import the Migrate events:
use Drupal\migrate\Event\MigrateImportEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Drupal\migrate\Event\MigrateEvents;
and After add our methods:
protected $staticCache;
public function __construct() {
$this->staticCache = &drupal_static("your_migration");
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
return [
MigrateEvents::PRE_IMPORT => 'onMigratePreImport',
MigrateEvents::POST_IMPORT => 'onMigratePostImport',
];
}
/**
* @param \Drupal\migrate\Event\MigrateImportEvent $event
* Import Event.
*/
public function onMigratePostImport(MigrateImportEvent $event) {
if ($event->getMigration()->getBaseId() == "your_migration") {
$this->staticCache = FALSE;
}
}
/**
* @param \Drupal\migrate\Event\MigrateImportEvent $event
* Import Event.
*/
public function onMigratePreImport(MigrateImportEvent $event) {
if ($event->getMigration()->getBaseId() == "your_migration") {
$this->staticCache = TRUE;
}
}
And that's it, now we have a flag which we can use to determine if we are running the migration or not, the complete class look like this:
namespace Drupal\your_module\EventSubscriber;
use Drupal\migrate\Event\MigrateImportEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Drupal\migrate\Event\MigrateEvents;
/**
* Event subscriber to avoid sending emails/tweets/facebook posts on migrations.
*/
class MigrationEvents implements EventSubscriberInterface {
/**
* The drupal_static cache.
*
* @var array
*/
protected $staticCache;
/**
* CommentEventSubscriber constructor.
*/
public function __construct() {
$this->staticCache = &drupal_static("your_migration");
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
return [
MigrateEvents::PRE_IMPORT => 'onMigratePreImport',
MigrateEvents::POST_IMPORT => 'onMigratePostImport',
];
}
/**
* @param \Drupal\migrate\Event\MigrateImportEvent $event
* Import Event.
*/
public function onMigratePostImport(MigrateImportEvent $event) {
if ($event->getMigration()->getBaseId() == "your_migration") {
$this->staticCache = FALSE;
}
}
/**
* @param \Drupal\migrate\Event\MigrateImportEvent $event
* Import Event.
*/
public function onMigratePreImport(MigrateImportEvent $event) {
if ($event->getMigration()->getBaseId() == "your_migration") {
$this->staticCache = TRUE;
}
}
}
And finally, We now can use this variable to determine if we should send that email when creating a new entity, for instance:
/**
* Implements hook_node_insert().
*/
function yourmodule_node_insert($entity) {
// If the migration is running, just return without doing anything.
if (drupal_static('your_migration', FALSE)) {
return;
}
// All your code for send emails/tweets here.
// . . .
}
And that's it.
Here we used drupal_static to preserve the value through the execution of the migration if you want to read more about it check here