You are here

protected function Migration::applyMappings in Migrate 7.2

Same name and namespace in other branches
  1. 6.2 includes/migration.inc \Migration::applyMappings()

Apply field mappings to a data row received from the source, returning a populated destination object.

3 calls to Migration::applyMappings()
Migration::analyze in includes/migration.inc
Perform an analysis operation - report on field values in the source.
Migration::import in includes/migration.inc
Perform an import operation - migrate items from source to destination.
XMLMigration::applyMappings in plugins/sources/xml.inc
A normal $data_row has all the input data as top-level fields - in this case, however, the data is embedded within a SimpleXMLElement object in $data_row->xml. Explode that out to the normal form, and pass on to the normal implementation.
1 method overrides Migration::applyMappings()
XMLMigration::applyMappings in plugins/sources/xml.inc
A normal $data_row has all the input data as top-level fields - in this case, however, the data is embedded within a SimpleXMLElement object in $data_row->xml. Explode that out to the normal form, and pass on to the normal implementation.

File

includes/migration.inc, line 1279
Defines the base class for import/rollback processes.

Class

Migration
The base class for all import objects. This is where most of the smarts of the migrate module resides. Migrations are created by deriving from this class, and in the constructor (after calling parent::__construct()) initializing at a minimum the name,…

Code

protected function applyMappings() {
  $this->destinationValues = new stdClass();
  foreach ($this
    ->getFieldMappings() as $mapping) {
    $destination = $mapping
      ->getDestinationField();

    // Skip mappings with no destination (source fields marked DNM)
    if ($destination) {
      $source = $mapping
        ->getSourceField();
      $default = $mapping
        ->getDefaultValue();

      // When updating existing items, make sure we don't create a destination
      // field that is not mapped to anything (a source field or a default value)
      if (!$source && !isset($default)) {
        continue;
      }
      $destination_values = NULL;

      // If there's a source mapping, and a source value in the data row, copy
      // to the destination
      if ($source && isset($this->sourceValues->{$source})) {
        $destination_values = $this->sourceValues->{$source};
      }
      elseif (!is_null($default)) {
        $destination_values = $default;
      }

      // If there's a separator specified for this destination, then it
      // will be populated as an array exploded from the source value
      $separator = $mapping
        ->getSeparator();
      if ($separator && isset($destination_values)) {
        if (is_array($separator)) {
          if (isset($separator['group separator'])) {
            $destination_values = explode($separator['group separator'], $destination_values);
          }
          else {
            $destination_values = array(
              $destination_values,
            );
          }
          foreach ($destination_values as $group => $value) {
            if (isset($separator['key separator'])) {
              $destination_values[$group] = explode($separator['key separator'], $value);
            }
            else {
              $destination_values[$group] = array(
                $value,
              );
            }
          }
        }
        else {
          $destination_values = explode($separator, $destination_values);
        }
      }

      // If a source migration is supplied, use the current value for this field
      // to look up a destination ID from the provided migration
      $source_migration = $mapping
        ->getSourceMigration();
      if ($source_migration && isset($destination_values)) {
        $destination_values = $this
          ->handleSourceMigration($source_migration, $destination_values, $default, $this);
      }

      // Call any designated callbacks
      $callbacks = $mapping
        ->getCallbacks();
      foreach ($callbacks as $callback) {
        if (isset($destination_values)) {
          $destination_values = call_user_func_array($callback['callback'], array_merge(array(
            $destination_values,
          ), $callback['params']));
        }
      }

      // If specified, assure a unique value for this property.
      $dedupe = $mapping
        ->getDedupe();
      if ($dedupe && isset($destination_values)) {
        $destination_values = $this
          ->handleDedupe($dedupe, $destination_values);
      }

      // Assign any arguments
      if (isset($destination_values)) {
        $arguments = $mapping
          ->getArguments();
        if ($arguments) {
          if (!is_array($destination_values)) {
            $destination_values = array(
              $destination_values,
            );
          }

          // TODO: Stuffing arguments into the destination field is gross - can
          // we come up with a better way to communicate them to the field
          // handlers?
          $destination_values['arguments'] = array();
          foreach ($arguments as $argname => $destarg) {
            if (is_array($destarg) && isset($destarg['source_field']) && property_exists($this->sourceValues, $destarg['source_field'])) {
              $destination_values['arguments'][$argname] = $this->sourceValues->{$destarg['source_field']};
            }
            elseif (is_array($destarg) && isset($destarg['default_value'])) {
              $destination_values['arguments'][$argname] = $destarg['default_value'];
            }
            else {
              $destination_values['arguments'][$argname] = $destarg;
            }
          }
        }
      }

      // Are we dealing with the primary value of the destination field, or a
      // subfield?
      $destination = explode($this->subfieldDelimiter, $destination);

      // Count how many levels of fields are in the mapping. We'll use the
      // last one.
      $destination_count = count($destination);
      $destination_field = $destination[0];
      if ($destination_count == 2) {
        $subfield = $destination[1];

        // We're processing the subfield before the primary value, initialize it
        if (!property_exists($this->destinationValues, $destination_field)) {
          $this->destinationValues->{$destination_field} = array();
        }
        elseif (!is_array($this->destinationValues->{$destination_field})) {
          $this->destinationValues->{$destination_field} = array(
            $this->destinationValues->{$destination_field},
          );
        }

        // Add the subfield value to the arguments array.
        $this->destinationValues->{$destination_field}['arguments'][$subfield] = $destination_values;
      }
      elseif ($destination_count == 3) {
        $subfield2 = $destination[2];

        // We're processing the subfield before the primary value, initialize it
        if (!property_exists($this->destinationValues, $destination_field)) {
          $this->destinationValues->{$destination_field} = array();
        }
        elseif (!is_array($this->destinationValues->{$destination_field})) {
          $this->destinationValues->{$destination_field} = array(
            $this->destinationValues->{$destination_field},
          );
        }

        // Additional check for case when first subfield doesn't exist.
        if (!isset($this->destinationValues->{$destination_field}['arguments'][$destination[1]])) {
          $this->destinationValues->{$destination_field}['arguments'][$destination[1]] = array();
        }
        elseif (!is_array($this->destinationValues->{$destination_field}['arguments'][$destination[1]])) {

          // Convert first subfield level to an array so we can add to it.
          $this->destinationValues->{$destination_field}['arguments'][$destination[1]] = array(
            $this->destinationValues->{$destination_field}['arguments'][$destination[1]],
          );
        }

        // Add the subfield value to the arguments array.
        $this->destinationValues->{$destination_field}['arguments'][$destination[1]]['arguments'][$subfield2] = $destination_values;
      }
      elseif (!property_exists($this->destinationValues, $destination_field)) {
        $this->destinationValues->{$destination_field} = $destination_values;
      }
      else {
        $this->destinationValues->{$destination_field} = array_merge((array) $destination_values, $this->destinationValues->{$destination_field});
      }
    }
  }
}