1

I'm trying to use the migrate module to create products. My issue is that I need to map data to a field that contains multiple values.

This is the exact case.

Product A has 3 prices,

  1. Stand Price
  2. Price for x to y qty
  3. Price for x yo -1 (unlimited)

Using the commerce price tables module this has created the field data table with 3 fields, price, min_qty, max_qty.

Is it possible to map data to a field that contains multiple columns(values) with the migrate module?

Also the data is coming from another database.

I have not had any success using the addFieldMapping() function in the migrate module.

Regards, Nathan.

3
  • Multivalue fields are supposed to be used when each value have the same meaning. In your case it looks like instead of one field with 3 price values, you should have 3 price fields, single value each.
    – Mołot
    Commented May 27, 2013 at 8:21
  • In this case, the price table module is using the multiple values correctly to interact with the product's "base_price" field during price calculation. Separate price fields aren't required, so I'd just look into how Migrate normally handles multi-value field values. I'm sure it can be done. Perhaps look in the Taxonomy integration? Commented May 28, 2013 at 0:01
  • Thanks @RyanSzrama, you pointed me in the right direction.
    – Nathan
    Commented May 28, 2013 at 5:49

1 Answer 1

2

I've worked it out. Migrate can handle multiple values but due to the commerce price table having its own field type of 'commerce_price_table' I've needed to create a field handler for this field type.

Mapping is done like this in the migration class:(machine name for this field is field_volume_price)

$this->addFieldMapping('field_volume_price', volume_price); 
$this->addFieldMapping('field_volume_price:currency_code',volume_price_min_qty);
$this->addFieldMapping('field_volume_price:min_qty',volume_price_max_qty);
$this->addFieldMapping('field_volume_price:max_qty',volume_price_currency_code');

Due to these fields holding arrays of data we need to create these in the prepareRow function in the migration class:

function prepareRow($row)  {
    foreach($row->product['volume_prices'] as $volume_price) { 
        $row->volume_price[] = $volume_price['price'];
        $row->volume_price_currency_code[] = $row->product['currency'];
        $row->volume_price_min_qty[] = $volume_price['minimumQuantity'];
        $row->volume_price_max_qty[] = '';//this is unknown in our data, this is set in the handler 
    }
}

If anyone is interested I've attached the handler. Also due to our set of data not containing the max qty value we had to work this out and set this in the arguments.(remove the loop if its set)

class ProductVolumePriceFieldHandler extends MigrateFieldHandler {
  public function __construct() {
    $this->registerTypes(array('commerce_price_table'));
  }


  public function fields($type) {
    // Declare our arguments to also be available as subfields.
    $fields = array(
      'currency_code'   => t('Subfield: Currency code for the field'),
      'min_qty'         => t('Subfield: Min Qty for the field'),
      'max_qty'         => t('Subfield: Max Qty for the field'),
    );
    return $fields;
  }

  public function prepare($entity, array $field_info, array $instance, array $values) {
    $migration = Migration::currentMigration();
    if (isset($values['arguments'])) {
      $arguments = $values['arguments'];
      unset($values['arguments']);
    }
    else {
      $arguments = array();
    }

    $language = $this->getFieldLanguage($entity, $field_info, $arguments);
    //we need to set the max value because the our data does not provide this
    if(isset($arguments['min_qty']) && !is_null($arguments['min_qty'])) {
        $minimumQuantity = $arguments['min_qty'];
        sort($minimumQuantity,SORT_NUMERIC);
        //create the max value of the ranges, eg:
        //min qty: 1,3,5,20
        //1-2,3-4,5-19,20--1

        //reconstruct the arguments array with qtys in order
        //$index becomes the new delta
        foreach($minimumQuantity as $index => $min){
            $args['currency_code'][$index]   = $arguments['currency_code'][array_search($min,$arguments['min_qty'])];
            $args['min_qty'][$index]         = $arguments['min_qty'][array_search($min,$arguments['min_qty'])];
            $args['max_qty'][$index]         = isset($minimumQuantity[$index+1])?$minimumQuantity[$index+1]-1:-1;
        }
        if(isset($args)){
            //set arguments array for new ording
            $arguments = $args;
        }
    }

    $delta = 0;
    foreach ($values as $value) {
        if(!is_null($value)) {
            $return[$language][$delta] = array('amount' => ($value * 100));
            if (isset($arguments['currency_code'])) {
                if (is_array($arguments['currency_code'])) {
                    $return[$language][$delta]['currency_code'] = $arguments['currency_code'][$delta];
                } else {
                    $return[$language][$delta]['currency_code'] = $arguments['currency_code'];
                }
            }
            if (isset($arguments['min_qty'])) {
                if (is_array($arguments['min_qty'])) {
                    $return[$language][$delta]['min_qty'] = $arguments['min_qty'][$delta];
                }else {
                    $return[$language][$delta]['min_qty'] = $arguments['min_qty'];
                }
            }
            if (isset($arguments['max_qty'])) {
                if (is_array($arguments['max_qty'])) {
                    $return[$language][$delta]['max_qty'] = $arguments['max_qty'][$delta];
                }else {
                    $return[$language][$delta]['max_qty'] = $arguments['max_qty'];
                }
            }
        }
        $delta++;
    }

    return isset($return) ? $return : NULL;

  }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.