Is there an established way of saving messages about the current record when you are in a prepareRow function? When skipping over rows due to bad data, it would be good to provide the user with an explanation.

I tried saving a migration message using the $this->saveMessage function, and the message was saved, but with the wrong source id. Apparently, $this->currentSourceKey is not set until it gets to the actual import function, and so when you save messages in the prepare row function, it uses the value of the previous record.

Thanks!

Comments

mikeryan’s picture

Version: 7.x-2.2 » 7.x-2.x-dev
Assigned: Unassigned » mikeryan
Status: Active » Postponed (maintainer needs more info)

We should probably replace the Migration class $currentSourceKey with a function calling through to $this->source->getCurrentKey().

mikeryan’s picture

Status: Postponed (maintainer needs more info) » Active
mikemccaffrey’s picture

It doesn't seem to just be an issue with knowing the key. It looks like messages are cleared at the beginning of the import() step, after all of the prepareRow functions are called, so even if the ID was known in the prepare phase, the messages would be cleared right afterwards.

Perhaps we could move that message clearing to the beginning, as soon as the migration is called? In the meantime, I added some custom functions to my migration class to save messages from the prepareRow functions and add them during the import phase:

  /**
   * saveMessage doesn't work in prepare function because import clears them, so save them for later
   */
  public function savePrepareMessage($message, $level = MigrationBase::MESSAGE_NOTICE) {
    $prepareMessage->message = $message;
    $prepareMessage->level = $level;
    $prepareMessage->sourceKey = $this->source->getCurrentKey();
    $this->prepareMessages[] = $prepareMessage;

    // trigger an error so it shows up when drush runs the migration
    if(function_exists("drush_log")) drush_log($message.": ".$prepareMessage->sourceKey['path']);
  }

  /**
   * save the messages after the normal import function is complete
   */
  protected function import() {
    $return = parent::import();

    // get the messages saved in prepareMessage
    if(isset($this->prepareMessages)) {
      foreach($this->prepareMessages as $message) {
        $this->map->saveMessage($message->sourceKey, $message->message, $message->level);
      }
    }
    return $return;
  }
David_Rothstein’s picture

Title: Saving messages in prepareRow » Allow messages to be saved in prepareRow()

I just ran into this problem and @mikemccaffrey's code worked perfectly for me (thanks Mike!).

I also agree that moving the message clearing earlier sounds like a good way to fix this.

mikeryan’s picture

Status: Active » Fixed

OK, I've added a queueMessage() method (same parameters as saveMessage()) along the lines of the approach above.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

joachim’s picture

Category: Feature request » Bug report
Issue summary: View changes
Status: Closed (fixed) » Active

So is it the case that saveMessage() can't be used in prepareRow()?

Should queueMessage() be used there instead? Should it always be used? Because having two different methods to record a message depending on where you are in the code seems rather complicated to me.

At the very least this needs documenting -- I just spent 15 minutes trying to figure out why my messages don't work.

mikeryan’s picture

Category: Bug report » Feature request
Status: Active » Closed (fixed)

Please don't reopen long-closed issues - open a fresh support request if you have a question relating to something that's already been committed.

That being said, the semi-redundant methods are because rearranging the main processing loop so saveMessage() would work in prepareRow() would mess with the existing sequence of events - I didn't see a way to do it without breaking something else, or doing some risky refactoring. queueMessage() should work fine wherever saveMessage() is used.

I added a note to #1965854: Update documentation for Migrate 2.6 to document queueMessage().