diff --git a/migrate_ui.routing.yml b/migrate_ui.routing.yml
index 133ee2f..f173811 100644
--- a/migrate_ui.routing.yml
+++ b/migrate_ui.routing.yml
@@ -45,3 +45,11 @@ entity.migration.delete_form:
_title: 'Delete migration'
requirements:
_entity_access: 'migration.delete'
+
+entity.migration.launch_form:
+ path: '/admin/config/migrate/migrations/launch/{migration}'
+ defaults:
+ _entity_form: 'migration.launch-form'
+ _title: 'Launch migration'
+ requirements:
+ _entity_access: 'migration.launch'
\ No newline at end of file
diff --git a/src/Form/LaunchMigrationForm.php b/src/Form/LaunchMigrationForm.php
new file mode 100644
index 0000000..4d29014
--- /dev/null
+++ b/src/Form/LaunchMigrationForm.php
@@ -0,0 +1,283 @@
+destinationField = $destination_field;
+ return parent::buildForm($form, $form_state);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function form(array $form, FormStateInterface $form_state) {
+ $form = parent::form($form, $form_state);
+
+ $form['operations'] = $this->migrateUiMigrateOperations();
+
+ return $form;
+ }
+
+
+
+ /**
+ * Get Operations.
+ */
+ private function migrateUiMigrateOperations() {
+ // Build the 'Update options' form.
+ $operations = array(
+ '#type' => 'fieldset',
+ '#title' => t('Operations'),
+ );
+
+ $options = array(
+ '' => t('Please select'),
+ 'import_immediate' => t('Import immediately'),
+ 'import_background' => t('Import in background'),
+ 'rollback_immediate' => t('Rollback immediately'),
+ 'rollback_background' => t('Rollback in background'),
+ );
+
+ $options += array(
+ 'stop' => t('Stop'),
+ 'reset' => t('Reset'),
+ 'deregister' => t('Remove migration settings'),
+ );
+ $operations['operation'] = array(
+ '#type' => 'select',
+ '#title' => t('Operation'),
+ '#title_display' => 'invisible',
+ '#options' => $options,
+ );
+ $operations['submit'] = array(
+ '#type' => 'submit',
+ '#value' => t('Execute'),
+ '#validate' => array('migrate_ui_migrate_validate'),
+ '#submit' => array('migrate_ui_migrate_submit'),
+ );
+ $operations['description'] = array(
+ '#prefix' => '
',
+ '#markup' => t(
+ 'Choose an operation to run on all selections above:
+
+ - Import
Imports all previously unprocessed records from the source, plus
+ any records marked for update, into destination Drupal objects.
+ - Rollback
Deletes all Drupal objects created by the import.
+ - Stop
Cleanly interrupts any import or rollback processes that may
+ currently be running.
+ - Reset
Sometimes a process may fail to stop cleanly, and be
+ left stuck in an Importing or Rolling Back status. Choose Reset to clear
+ the status and permit other operations to proceed.
+ - Remove migration settings
Removes all information about a migration group
+ or task, while preserving any content that has already been imported.
+
'
+ ),
+ '#postfix' => '',
+ );
+
+ $operations['options'] = array(
+ '#type' => 'fieldset',
+ '#title' => t('Options'),
+ '#collapsible' => TRUE,
+ '#collapsed' => TRUE,
+ );
+ $operations['options']['update'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Update'),
+ '#description' => t('Check this box to update all previously-imported content
+ in addition to importing new content. Leave unchecked to only import
+ new content'),
+ );
+ $operations['options']['force'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Ignore dependencies'),
+ '#description' => t('Check this box to ignore dependencies when running imports
+ - all tasks will run whether or not their dependent tasks have
+ completed.'),
+ );
+ $operations['options']['limit'] = array(
+ '#tree' => TRUE,
+ '#type' => 'fieldset',
+ '#attributes' => array('class' => array('container-inline')),
+ 'value' => array(
+ '#type' => 'textfield',
+ '#title' => t('Limit to:'),
+ '#size' => 10,
+ ),
+ 'unit' => array(
+ '#type' => 'select',
+ '#options' => array(
+ 'items' => t('items'),
+ 'seconds' => t('seconds'),
+ ),
+ '#description' => t('Set a limit of how many items to process for
+ each migration task, or how long each should run.'),
+ ),
+ );
+
+ return $operations;
+ }
+
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validateForm(array &$form, FormStateInterface $form_state) {
+
+ if (empty($form_state->getValue('operation'))) {
+ $form_state->setErrorByName('operation', $this->t('Please select an operation.'));
+ return;
+ }
+
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function submitForm(array &$form, FormStateInterface $form_state) {
+
+ $operation = $form_state->getValue('operation');
+
+ $limit = $form_state->getValue('limit');
+
+ if ($form_state->getValue('update')) {
+ $update = $form_state->getValue('update');
+ }
+ else {
+ $update = 0;
+ }
+ if ($form_state->getValue('force')) {
+ $force = $form_state->getValue('force');
+ }
+ else {
+ $force = 0;
+ }
+
+ $migration_name = \Drupal::routeMatch()->getParameter('migration');
+ $machine_name = $migration_name->id();
+
+ $operations = array();
+
+ $drush_arguments = array();
+ if ($machine_name) {
+ //TODO $migration = Migration::getInstance($machine_name);
+ //TODO if ($migration) {
+ switch ($operation) {
+ case 'import_immediate':
+ // Update (if necessary) once, before starting
+ if ($update && method_exists($migration, 'prepareUpdate')) {
+ //TODO $migration->prepareUpdate();
+ }
+ $operations[] = array('migrate_ui_batch', array('import', $machine_name, $limit, $force));
+ break;
+ case 'rollback_immediate':
+ $operations[] = array('migrate_ui_batch', array('rollback', $machine_name, $limit, $force));
+ break;
+ case 'import_background':
+ case 'rollback_background':
+ $drush_arguments[] = $machine_name;
+ break;
+ case 'stop':
+ //$migration->stopProcess();
+ break;
+ case 'reset':
+ //$migration->resetStatus();
+ break;
+ case 'deregister':
+ //migrate_ui_deregister_migration($machine_name);
+ break;
+ //TODO}
+ }
+ }
+
+ // Only immediate rollback and import operations will need to go through Batch API.
+ if (count($operations) > 0) {
+
+ $batch = array(
+ 'operations' => $operations,
+ 'title' => t('Import processing'),
+ 'file' => drupal_get_path('module', 'migrate_ui') . '/migrate_ui.pages.inc',
+ 'init_message' => t('Starting import process'),
+ 'progress_message' => t(''),
+ 'error_message' => t('An error occurred. Some or all of the import processing has failed.'),
+ 'finished' => 'migrate_ui_batch_finish',
+ );
+ batch_set($batch);
+
+ }
+ elseif (count($drush_arguments) > 0) {
+ kint('la');
+ trim(variable_get('migrate_drush_path', ''));
+ // Check that $drush_path works. See migrate_ui_configure_form().
+ if (!is_executable($drush_path)) {
+ $message = t('To enable running operations in the background with drush, (which is recommended), some configuration must be done on the server. See the documentation on drupal.org.',
+ array(
+ '@drush' => 'http://drupal.org/project/drush',
+ '@recommended' => 'http://drupal.org/node/1806824',
+ '@config' => 'http://drupal.org/node/1958170',
+ '@dorg' => 'http://drupal.org/',
+ )
+ );
+ drupal_set_message($message);
+ return;
+ }
+ $uri = $GLOBALS['base_url'];
+ $uid = $GLOBALS['user']->uid;
+ if ($operation == 'import_background') {
+ $command = 'mi';
+ $log_suffix = '.import.log';
+ }
+ else {
+ $command = 'mr';
+ $log_suffix = '.rollback.log';
+ }
+ $migrations = implode(',', $drush_arguments);
+ $drush_command = "$drush_path $command $migrations --user=$uid --uri=$uri " .
+ '--root=' . DRUPAL_ROOT;
+ if ($force) {
+ $drush_command .= ' --force';
+ }
+ if ($update) {
+ $drush_command .= ' --update';
+ }
+ if (variable_get('migrate_drush_mail', 0)) {
+ $drush_command .= ' --notify';
+ }
+ if (!empty($limit['value'])) {
+ $limit = $limit['value'] . ' ' . $limit['unit'];
+ $drush_command .= " --limit=\"$limit\"";
+ }
+ $log_file = drupal_realpath('temporary://' . $drush_arguments[0] . $log_suffix);
+ $drush_command .= " >$log_file 2>&1 &";
+ exec($drush_command, $output, $status);
+ if (variable_get('migrate_drush_mail', 0)) {
+ drupal_set_message('Your operation is running in the background. You will receive an email message when it is complete.');
+ }
+ else {
+ drupal_set_message('Your operation is running in the background. You may '.
+ 'refresh the dashboard page to check on its progress.');
+ }
+ }
+ }
+
+}
diff --git a/src/MigrationListBuilder.php b/src/MigrationListBuilder.php
index ad23ee8..0b0ee43 100644
--- a/src/MigrationListBuilder.php
+++ b/src/MigrationListBuilder.php
@@ -59,6 +59,8 @@ class MigrationListBuilder extends ConfigEntityListBuilder {
$row['destination'] = $this->t('Destination name');
$row['tags'] = $this->t('Tags');
$row['operations'] = $this->t('Operations');
+ $row['import'] = $this->t('Import');
+
return $row;
}
@@ -72,6 +74,15 @@ class MigrationListBuilder extends ConfigEntityListBuilder {
$row['destination']['data'] = $entity->getDestinationPlugin()->getPluginId();
$row['tags']['data'] = implode(', ', $entity->get('migration_tags') ?: []);
$row['operations']['data'] = $this->buildOperations($entity);
+ $row['import']['data'] = array(
+ '#type' => 'dropbutton',
+ '#links' => array(
+ 'simple_form' => array(
+ 'title' => $this->t('Launch'),
+ 'url' => Url::fromRoute('entity.migration.launch_form', array('migration' => $entity->get('id'))),
+ ),
+ ),
+ );
return $row;
}