Migración de archivos CSV desde la interfaz de usuario

Posted by Charlotte León on June 13, 2017
Migration & Upgrades
Development

El tema de la migración de datos de un archivo CSV ha sido de mucho interés para MTech y para el proceso de desarrollo, si tú aún no te has familiarizado con este tipo de migración, te invito a que eches un vistazo a nuestros blogs anteriores acerca de ello: Migrar usando CSV.

NOTA: Nuestros módulos personalizados son generados a través de Drupal Console

Ahora podemos entrar de lleno a lo que será está migración. En primer lugar previamente tenemos en existencia 2 módulos personalizados para cada tipo de migración CSV, en este caso program_migrate con nuestro archivo yaml migrate_plus.migration.program_csv.yml que sería este:

langcode: en
status: true
dependencies:
  enforced:
    module:
      - program_migrate
id: program_csv
label: Program CSV file migration
migration_tags:
  - CSV
source:
  plugin: csv
  path: 'public://csv/programs.csv'
  header_row_count: 1
  keys:
    - "Program Name"
process:
  type:
    plugin: default_value
    default_value: course
  uid:
    plugin: default_value
    default_value: 1
  title: Long Title
  field_short_title: Short Title
  body: Description
  field_program_id: Program Name
  field_program_status: Current Program Status
  field_program_transfer_status: Transfer Status
destination:
  plugin: entity:node
migration_dependencies:
  required: {}
  optional: {}

y el otro módulo reward_migrate con el archivo yaml migrate_plus.migration.reward_csv.yml:

langcode: en
status: true
dependencies:
  enforced:
    module:
      - reward_migrate
id: reward_csv
label: Award CSV file migration
migration_tags:
  - CSV
source:
  plugin: csv
  path: 'public://csv/rewards.csv'
  header_row_count: 1
  keys:
    - id
process:
  type:
    plugin: default_value
    default_value: award
  uid:
    plugin: default_value
    default_value: 1
  title: name
  body: description
  field_award_application_deadline: applicationDeadline
  field_award_id: id
  field_award_category: category
  field_award_value: value
  field_number_awarded: numberAwarded
destination:
  plugin: entity:node
migration_dependencies:
  required: {}
  optional: {}

Crearemos un tercer módulo personalizado prueba_import y en nuestro archivo prueba_import.info.yml las dependencias serán nuestros módulos anteriores: program_migrate y reward_migrate.

Con Drupal Console vamos a generar nuestra formulario con el comando $ drupal generate:form 

<?php

namespace Drupal\prueba_import\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\prueba_import\PruebaMigrateMessage;
use Drupal\migrate\MigrateExecutable;
use Drupal\migrate\MigrateMessage;
use Drupal\migrate\Plugin\Migration;
use Drupal\migrate\Plugin\MigrationInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\migrate\Plugin\MigrationPluginManager;

/**
 * Class ImportForm.
 *
 * @package Drupal\prueba_import\Form
 */
class ImportForm extends FormBase {

  /**
   * Drupal\migrate\Plugin\MigrationPluginManager definition.
   *
   * @var \Drupal\migrate\Plugin\MigrationPluginManager
   */
  protected $pluginManagerMigration;
  /**
   * Constructs a new ImportForm object.
   */
  public function __construct(
    MigrationPluginManager $plugin_manager_migration
  ) {
    $this->pluginManagerMigration = $plugin_manager_migration;
  }

  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('plugin.manager.migration')
    );
  }


  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'import_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form['type_of_csv'] = [
      '#type' => 'select',
      '#title' => $this->t('Type of CSV'),
      '#options' => [
        'reward' => $this->t('Rewards'),
        'program' => $this->t('Programs')
      ],
      '#size' => 1,
    ];
    $form['upload_csv'] = [
      '#type' => 'file',
      '#title' => $this->t('Upload CSV'),
    ];
    $form['update_existing_records'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Update existing records'),
      '#default_value' => 1,
    ];
    $form['import'] = [
      '#type' => 'submit',
      '#value' => $this->t('Import'),
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
    parent::validateForm($form, $form_state);
  
    $validators = ['file_validate_extensions' => ['csv']];
    $file = file_save_upload('upload_csv', $validators, FALSE, 0);
    if (isset($file)) {
      // File upload was attempted.
      if ($file) {
        $form_state->setValue('csv_path', $file->getFileUri());
      }
      else {
        // File upload failed.
        $form_state->setErrorByName('upload_csv', $this->t('The CSV file could not be uploaded.'));
      }
    }
    
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $migration = 'reward_csv';
    switch ($form_state->getValue('type_of_csv')) {
      case 'reward':
        $migration = 'reward_csv';
        break;
    
    case 'program':
      $migration = 'program_csv';
      break;
    }
  
    /** @var Migration $migrationInstance */
    $definition = $this->pluginManagerMigration->getDefinition($migration);
    // Alter source file path from validator above.
    $definition['source']['path'] = $form_state->getValue('csv_path') ;
    $migrationInstance = $this->pluginManagerMigration->createStubMigration($definition);
    
    // Reset status.
    $status = $migrationInstance->getStatus();
    if ($status != MigrationInterface::STATUS_IDLE) {
      $migrationInstance->setStatus(MigrationInterface::STATUS_IDLE);
      drupal_set_message($this->t('Migration @id reset to Idle', ['@id' => $migration]), 'warning');
    }
    
    // Force updates or not.
    if ($form_state->getValue('update_existing_records')) {
      $migrationInstance->getIdMap()->prepareUpdate();
    }
    
    $executable = new MigrateExecutable($migrationInstance, new PruebaMigrateMessage());
    $result = $executable->import();
    
    if ($result ==  MigrationInterface::RESULT_COMPLETED) {
      drupal_set_message($this->t('Import was successful'));
    }
    else {
      drupal_set_message($this->t('The import was not successful, please review logs.'));
    }
  }

}

y creamos la clase personalizada PruebaMigrateMessage.php :

<?php

namespace Drupal\prueba_import;

use Drupal\migrate\MigrateMessageInterface;

class PruebaMigrateMessage implements MigrateMessageInterface {

  /**
   * Output a message from the migration.
   *
   * @param string $message
   *   The message to display.
   * @param string $type
   *   The type of message to display.
   *
   * @see drupal_set_message()
   */
  public function display($message, $type = 'status') {
    drupal_set_message($message, $type);
  }

}

Siempre con el uso de Drupal Console generamos dos nuevos archivos necesarios para la migración; routing y permissions.

Puedes obtener el código completo en git!

 

 

¿Está buscando ayuda para una migración o actualización de Drupal? Independientemente de la complejidad del sitio o de los datos, MTech puede ayudarle a pasar de un CMS privado o actualizarlo a la última versión: Drupal 8.

Escríbanos sobre su proyecto y nos pondremos en contacto con usted dentro de 48 horas.


Migración de archivos CSV desde la interfaz de usuario