Migrate location filed from Drupal 6 to Geofield filed Drupal 8

Profile picture for user a.berramou
Azz-eddine BERRAMOU 22 April, 2020

One of my clients just migrate his site from Drupal 6 to Drupal 8, he was using Location module, but this module not been ported according to this issue, so we had to use Geofield Module to replace it.

Now all migrated content without location field, the question is:

How to migrate data form Drupal 6 location field to Drupal 8 Geofield field ?

  1. Defining the source database connection (Drupal 6 database)
    Add the following to your settings.php

    <?php
    
    $databases['migrate']['default'] = array (
      'database'  => 'source-database-name',
      'username'  => 'source-database-username',
      'password'  => 'source-database-password',
      'host'      => 'source-database-server',
      'port'      => '3306',
      'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
      'driver'    => 'mysql',
    );
  2. Create migrate source plugin
    To do so create class (let's call it MigrateLocation) inside MODULE_NAME/src/Plugin/migrate/source and put in it the following:

    <?php
    
    namespace Drupal\MODULE_NAME\Plugin\migrate\source;
    
    use Drupal\migrate\Plugin\migrate\source\SqlBase;
    use Drupal\migrate\Row;
    
    /**
     * Location field source plugin.
     *
     * @MigrateSource(
     *   id = "location_field",
     *   source_module = "MODULE_NAME",
     * )
     */
    class MigrateLocation extends SqlBase {
    
      /**
       * {@inheritdoc}
       */
      public function query() {
        // Source data is queried from 'location' table.
        $query = $this->select('location', 'l ');
        $query->leftJoin('location_instance', 'li', 'l.lid=li.lid');
        $query->fields('l', [
          'lid',
          'latitude',
          'longitude',
        ])
          ->fields('li', [
            'nid',
          ]);
        return $query;
      }
    
      /**
       * {@inheritdoc}
       */
      public function fields() {
        $fields = [
          'lid'       => $this->t('Location id'),
          'latitude'  => $this->t('latitude'),
          'longitude' => $this->t('longitude'),
          'nid'       => $this->t('Nid'),
        ];
        return $fields;
      }
    
      /**
       * {@inheritdoc}
       */
      public function getIds() {
        return [
          'lid' => [
            'type'  => 'integer',
            'alias' => 'l',
          ],
        ];
      }
    
      /**
       * {@inheritdoc}
       */
      public function prepareRow(Row $row) {
        // Get latitude.
        $latitude = $row->getSourceProperty('latitude');
        // Get longitude.
        $longitude = $row->getSourceProperty('longitude');
        // Get the node id.
        $nid = $row->getSourceProperty('nid');
        // Set source properties.
        $row->setSourceProperty('lat', $latitude);
        $row->setSourceProperty('lon', $longitude);
        $row->setSourceProperty('nid', $nid);
        return parent::prepareRow($row);
      }
    
    }
    
  3. Use you plugin as source to update your nodes and populate your geofield fields.
    In your migration yml  for example (config/install/migrate_plus.migration.beer_content.yml) file you can use it as the following 

    # Migration configuration for beer content.
    id: beer_content
    label: Import beer geofield fields.
    migration_group: default
    
    source:
      # Call our source plugin created in step 2
      plugin: location_field
      target: db_migration
      data_rows:
        -
          lid: 'lid'
          lat: 'lat'
          lon: 'lon'
          nid: 'nid'
      ids:
        lid:
          type: integer
    
    process:
      type:
        plugin: default_value
        default_value: beer
      nid: nid
      field_geolocation:
        -
          plugin: geofield_latlon
          source:
            - lat
            - lon
    
    destination:
      plugin: entity:node
      default_bundle: beer
      overwrite_properties:
        - field_geolocation
    
  4. Clear cache.
  5. Import your migration config you can use drush config-import with the following drush command.

    drush cim --partial --source=modules/custom/MODULE_NAME/config/install/
  6. Execute your migrate either using UI (if you have migrate ui enabled) or using Drush. 

    drush mim beer_content --update

        See Drush Migrate Tools commands page for more useful command drush for migration.
 
Required Modules (make sure those modules are installed and enabled):

Done!