Migración de archivos CSV desde la interfaz de usuario

Publicado por el 13 de Junio de 2017

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.