I am following this example in wine.inc:

    // TIP: You can apply one or more functions to a source value using
    // ->callbacks(). The function must take a single argument and return a
    // value which is a transformation of the argument. As this example shows,
    // you can have multiple callbacks, and they can either be straight
    // functions or class methods. In this case, our custom method prepends
    // 'review: ' to the body, and then we call a standard Drupal function to
    // uppercase the whole body.
    $this->addFieldMapping('body', 'body')
         ->callbacks(array($this, 'addTitlePrefix'), 'drupal_strtoupper');
    $this->addFieldMapping('body:summary', 'excerpt');

However, in my callback, I am performing a transformation to the value based on a mapping:

  protected function myFieldMappingCallback($source_data) {
    $map = array(
      'green' => 'apple',
      'yellow' => 'banana',
    );
    if (!isset($map[$source_data)) {
      // Log a message.
      return 'unknown';
    }
    return $map[$source_data];
}

I'd obviously like to include some details in the message I log, such as the row ID. But AFAIK I can't access that from inside the callback.

I suggest that the callback have a $row parameter added to its signature.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

13rac1’s picture

You can do this in prepareRow() without changing the module.

joachim’s picture

Yes, definitely.

However, I got the impression that using a callback for this was preferable. Certainly from my point of view it's cleaner, as it segments the different parts of the pre-processing into different methods: instead of one giant prepareRow() method that's hard to read, there's a series of callback methods, each of which has a single task to perform.

13rac1’s picture

Instead of a large prepareRow(), you can make separate functions for each "prepareField". I'm almost to the point doing that on my main migration.

joachim’s picture

True -- but if you do that, then why bother having the callback at all?

13rac1’s picture

I'm using the callbacks for simple formatting. Here is one that I'm using to make sure the title doesn't cause SQL problems. I'm getting the full title in a long text field:

  protected function shortenTitle($value) {
    return trim(mb_substr($value, 0, 255));
  }

But, yeah, you can argue against the existence of callbacks.

joachim’s picture

Status: Active » Needs review
FileSize
1.95 KB

This has come up again on a different project.

Here's a patch.

Status: Needs review » Needs work

The last submitted patch, 6: 2223057.migrate.field-mapping-callback-row-param.patch, failed testing.

joachim’s picture

Hmm, possibly redundant now I look at it some more, as you can use $this->sourceValues in the migration class.

But then, methods such as prepareRow() work with a $row parameter, so would be nice to be consistent.