/**
  * Builds a row for an entity in the entity listing.
  *
  * @param EntityInterface $migration
  *   The entity for which to build the row.
  *
  * @return array
  *   A render array of the table row for displaying the entity.
  *
  * @see Drupal\Core\Entity\EntityListController::render()
  */
 public function buildRow(MigrationInterface $migration)
 {
     $row['label'] = $migration->label();
     $row['machine_name'] = $migration->id();
     $row['status'] = $migration->getStatusLabel();
     // Derive the stats
     $source_plugin = $migration->getSourcePlugin();
     $row['total'] = $source_plugin->count();
     $map = $migration->getIdMap();
     $row['imported'] = $map->importedCount();
     // -1 indicates uncountable sources.
     if ($row['total'] == -1) {
         $row['total'] = $this->t('N/A');
         $row['unprocessed'] = $this->t('N/A');
     } else {
         $row['unprocessed'] = $row['total'] - $map->processedCount();
     }
     $group = $migration->get('migration_group');
     if (!$group) {
         $group = 'default';
     }
     // @todo: This is most likely not a Best Practice (tm).
     $row['messages']['data']['#markup'] = '<a href="/admin/structure/migrate/manage/' . $group . '/migrations/' . $migration->id() . '/messages">' . $map->messageCount() . '</a>';
     $migrate_last_imported_store = \Drupal::keyValue('migrate_last_imported');
     $last_imported = $migrate_last_imported_store->get($migration->id(), FALSE);
     if ($last_imported) {
         /** @var DateFormatter $date_formatter */
         $date_formatter = \Drupal::service('date.formatter');
         $row['last_imported'] = $date_formatter->format($last_imported / 1000, 'custom', 'Y-m-d H:i:s');
     } else {
         $row['last_imported'] = '';
     }
     return $row;
     // + parent::buildRow($migration);
 }
Example #2
0
 /**
  * Test row skipping when we can't get an entity to save.
  *
  * @covers ::import
  * @expectedException \Drupal\migrate\MigrateException
  * @expectedExceptionMessage Unable to get entity
  */
 public function testImportEntityLoadFailure()
 {
     $bundles = [];
     $destination = new EntityTestDestination([], '', [], $this->migration->reveal(), $this->storage->reveal(), $bundles, $this->entityManager->reveal(), $this->prophesize(FieldTypePluginManagerInterface::class)->reveal());
     $destination->setEntity(FALSE);
     $destination->import(new Row([], []));
 }
Example #3
0
 /**
  * @covers ::processCckFieldValues
  */
 public function testProcessBooleanTextExplicitValues()
 {
     $info = array('widget_type' => 'optionwidgets_onoff', 'global_settings' => array('allowed_values' => "foo|Foo\nbaz|Baz"));
     $this->plugin->processCckFieldValues($this->migration, 'field', $info);
     $expected = ['value' => ['plugin' => 'static_map', 'source' => 'value', 'default_value' => 0, 'map' => ['baz' => 1]]];
     $this->assertSame($expected, $this->migration->getProcess()['process']);
 }
 /**
  * {@inheritdoc}
  */
 public function processFieldFormatter(MigrationInterface $migration)
 {
     $process = [];
     foreach ($this->getFieldFormatterMap() as $source_format => $destination_format) {
         $process[0]['map'][$this->pluginId][$source_format] = $destination_format;
     }
     $migration->mergeProcessOfProperty('options/type', $process);
 }
Example #5
0
/**
 * Allows adding data to a row before processing it.
 *
 * For example, filter module used to store filter format settings in the
 * variables table which now needs to be inside the filter format config
 * file. So, it needs to be added here.
 *
 * hook_migrate_MIGRATION_ID_prepare_row is also available.
 */
function hook_migrate_prepare_row(Row $row, MigrateSourceInterface $source, MigrationInterface $migration)
{
    if ($migration->id() == 'd6_filter_formats') {
        $value = $source->getDatabase()->query('SELECT value FROM {variable} WHERE name = :name', array(':name' => 'mymodule_filter_foo_' . $row->getSourceProperty('format')))->fetchField();
        if ($value) {
            $row->setSourceProperty('settings:mymodule:foo', unserialize($value));
        }
    }
}
Example #6
0
 /**
  * {@inheritdoc}
  */
 public function prepareRow(Row $row)
 {
     $result_hook = $this->getModuleHandler()->invokeAll('migrate_prepare_row', array($row, $this, $this->migration));
     $result_named_hook = $this->getModuleHandler()->invokeAll('migrate_' . $this->migration->id() . '_prepare_row', array($row, $this, $this->migration));
     // If any of the hooks returned false, we want to skip the row.
     if ($result_hook && in_array(FALSE, $result_hook) || $result_named_hook && in_array(FALSE, $result_named_hook)) {
         return FALSE;
     }
 }
Example #7
0
 /**
  * {@inheritdoc}
  */
 public function processCckFieldValues(MigrationInterface $migration, $field_name, $data)
 {
     // The data is stored differently depending on whether we're using
     // db storage.
     $value_key = $data['db_storage'] ? $field_name : "{$field_name}/value";
     $format_key = $data['db_storage'] ? $field_name . '_format' : "{$field_name}/format";
     $migration->setProcessOfProperty("{$field_name}/value", $value_key);
     // See \Drupal\migrate_drupal\Plugin\migrate\source\d6\User::baseFields(),
     // signature_format for an example of the YAML that represents this
     // process array.
     $process = [['plugin' => 'static_map', 'bypass' => TRUE, 'source' => $format_key, 'map' => [0 => NULL]], ['plugin' => 'skip_on_empty', 'method' => 'process'], ['plugin' => 'migration', 'migration' => 'd6_filter_format', 'source' => $format_key]];
     $migration->mergeProcessOfProperty("{$field_name}/format", $process);
 }
Example #8
0
 /**
  * {@inheritdoc}
  */
 public function saveIdMapping(Row $row, array $destination_id_values, $source_row_status = MigrateIdMapInterface::STATUS_IMPORTED, $rollback_action = MigrateIdMapInterface::ROLLBACK_DELETE)
 {
     // Construct the source key.
     $source_id_values = $row->getSourceIdValues();
     // Construct the source key and initialize to empty variable keys.
     $keys = array();
     foreach ($this->sourceIdFields() as $field_name => $key_name) {
         // A NULL key value will fail.
         if (!isset($source_id_values[$field_name])) {
             $this->message->display(t('Could not save to map table due to NULL value for key field @field', array('@field' => $field_name)), 'error');
             return;
         }
         $keys[$key_name] = $source_id_values[$field_name];
     }
     $fields = array('source_row_status' => (int) $source_row_status, 'rollback_action' => (int) $rollback_action, 'hash' => $row->getHash());
     $count = 0;
     foreach ($destination_id_values as $dest_id) {
         $fields['destid' . ++$count] = $dest_id;
     }
     if ($count && $count != count($this->destinationIdFields())) {
         $this->message->display(t('Could not save to map table due to missing destination id values'), 'error');
         return;
     }
     if ($this->migration->get('trackLastImported')) {
         $fields['last_imported'] = time();
     }
     if ($keys) {
         // Notify anyone listening of the map row we're about to save.
         $this->eventDispatcher->dispatch(MigrateEvents::MAP_SAVE, new MigrateMapSaveEvent($this, $keys + $fields));
         $this->getDatabase()->merge($this->mapTableName())->key($keys)->fields($fields)->execute();
     }
 }
Example #9
0
File: Sql.php Project: scratch/gai
 /**
  * {@inheritdoc}
  */
 public function deleteBulk(array $source_id_values)
 {
     // If we have a single-column key, we can shortcut it.
     if (count($this->migration->getSourcePlugin()->getIds()) == 1) {
         $sourceids = array();
         foreach ($source_id_values as $source_id) {
             // Notify anyone listening of the map rows we're about to delete.
             $this->eventDispatcher->dispatch(MigrateEvents::MAP_DELETE, new MigrateMapDeleteEvent($this, $source_id));
             $sourceids[] = $source_id;
         }
         $this->getDatabase()->delete($this->mapTableName())->condition('sourceid1', $sourceids, 'IN')->execute();
         $this->getDatabase()->delete($this->messageTableName())->condition('sourceid1', $sourceids, 'IN')->execute();
     } else {
         foreach ($source_id_values as $source_id) {
             // Notify anyone listening of the map rows we're deleting.
             $this->eventDispatcher->dispatch(MigrateEvents::MAP_DELETE, new MigrateMapDeleteEvent($this, $source_id));
             $map_query = $this->getDatabase()->delete($this->mapTableName());
             $message_query = $this->getDatabase()->delete($this->messageTableName());
             $count = 1;
             foreach ($source_id as $key_value) {
                 $map_query->condition('sourceid' . $count, $key_value);
                 $message_query->condition('sourceid' . $count++, $key_value);
             }
             $map_query->execute();
             $message_query->execute();
         }
     }
 }
Example #10
0
 /**
  * {@inheritdoc}
  *
  * The migration iterates over rows returned by the source plugin. This
  * method determines the next row which will be processed and imported into
  * the system.
  *
  * The method tracks the source and destination IDs using the ID map plugin.
  *
  * This also takes care about highwater support. Highwater allows to reimport
  * rows from a previous migration run, which got changed in the meantime.
  * This is done by specifying a highwater field, which is compared with the
  * last time, the migration got executed (originalHighWater).
  */
 public function next()
 {
     $this->currentSourceIds = NULL;
     $this->currentRow = NULL;
     // In order to find the next row we want to process, we ask the source
     // plugin for the next possible row.
     while (!isset($this->currentRow) && $this->getIterator()->valid()) {
         $row_data = $this->getIterator()->current() + $this->configuration;
         $this->getIterator()->next();
         $row = new Row($row_data, $this->migration->getSourcePlugin()->getIds(), $this->migration->get('destinationIds'));
         // Populate the source key for this row.
         $this->currentSourceIds = $row->getSourceIdValues();
         // Pick up the existing map row, if any, unless getNextRow() did it.
         if (!$this->mapRowAdded && ($id_map = $this->idMap->getRowBySource($this->currentSourceIds))) {
             $row->setIdMap($id_map);
         }
         // Clear any previous messages for this row before potentially adding
         // new ones.
         if (!empty($this->currentSourceIds)) {
             $this->idMap->delete($this->currentSourceIds, TRUE);
         }
         // Preparing the row gives source plugins the chance to skip.
         if ($this->prepareRow($row) === FALSE) {
             continue;
         }
         // Check whether the row needs processing.
         // 1. This row has not been imported yet.
         // 2. Explicitly set to update.
         // 3. The row is newer than the current highwater mark.
         // 4. If no such property exists then try by checking the hash of the row.
         if (!$row->getIdMap() || $row->needsUpdate() || $this->aboveHighwater($row) || $this->rowChanged($row)) {
             $this->currentRow = $row->freezeSource();
         }
     }
 }
 /**
  * Tests the processRow method with an empty pipeline.
  */
 public function testProcessRowEmptyPipeline()
 {
     $this->migration->expects($this->once())->method('getProcessPlugins')->with(NULL)->will($this->returnValue(array('test' => array())));
     $row = new Row(array(), array());
     $this->executable->processRow($row);
     $this->assertSame($row->getDestination(), array());
 }
Example #12
0
 /**
  * {@inheritdoc}
  */
 public function processCckFieldValues(MigrationInterface $migration, $field_name, $field_info)
 {
     if ($field_info['widget_type'] == 'optionwidgets_onoff') {
         $process = ['value' => ['plugin' => 'static_map', 'source' => 'value', 'default_value' => 0]];
         $checked_value = explode("\n", $field_info['global_settings']['allowed_values'])[1];
         if (strpos($checked_value, '|') !== FALSE) {
             $checked_value = substr($checked_value, 0, strpos($checked_value, '|'));
         }
         $process['value']['map'][$checked_value] = 1;
     } else {
         // See \Drupal\migrate_drupal\Plugin\migrate\source\d6\User::baseFields(),
         // signature_format for an example of the YAML that represents this
         // process array.
         $process = ['value' => 'value', 'format' => [['plugin' => 'static_map', 'bypass' => TRUE, 'source' => 'format', 'map' => [0 => NULL]], ['plugin' => 'skip_on_empty', 'method' => 'process'], ['plugin' => 'migration', 'migration' => ['d6_filter_format', 'd7_filter_format'], 'source' => 'format']]];
     }
     $process = array('plugin' => 'iterator', 'source' => $field_name, 'process' => $process);
     $migration->setProcessOfProperty($field_name, $process);
 }
 /**
  * Tests the walk process plugin with multiple values.
  */
 public function testWalkWithMultipleValues()
 {
     // Set source value.
     $source_value = ['FOO', 'BAR', 'foobar'];
     // Set expected value;
     $expected_value = ['*Foo (mapped)*', '*Bar*', '*123*'];
     // Manually create the plugins. Migration::getProcessPlugins does this
     // normally, but the plugin system is not available.
     $process_plugins = $this->getProcessPlugins();
     // Define the value of getProcessPlugin() for every time processRow() is
     // called (number of values). See the count of $source_value.
     foreach (range(1, count($source_value)) as $key) {
         $this->migration->expects($this->at($key))->method('getProcessPlugins')->will($this->returnValue($process_plugins));
     }
     // Get migrate executable.
     $migrate_executable = $this->getMigrateExecutable();
     // Assert the value after running the process plugins.
     $plugin = new Walk($this->getWalkProcessPluginConfiguration(), 'walk', []);
     $new_value = $plugin->transform($source_value, $migrate_executable, new Row([], []), 'test');
     $this->assertSame($new_value, $expected_value);
 }
Example #14
0
 protected function mapJoinable()
 {
     if (!$this->getIds()) {
         return FALSE;
     }
     $id_map = $this->migration->getIdMap();
     if (!$id_map instanceof Sql) {
         return FALSE;
     }
     $id_map_database_options = $id_map->getDatabase()->getConnectionOptions();
     $source_database_options = $this->getDatabase()->getConnectionOptions();
     foreach (array('username', 'password', 'host', 'port', 'namespace', 'driver') as $key) {
         if ($id_map_database_options[$key] != $source_database_options[$key]) {
             return FALSE;
         }
     }
     return TRUE;
 }
 /**
  * {@inheritdoc}
  *
  * The migration iterates over rows returned by the source plugin. This
  * method determines the next row which will be processed and imported into
  * the system.
  *
  * The method tracks the source and destination IDs using the ID map plugin.
  *
  * This also takes care about highwater support. Highwater allows to reimport
  * rows from a previous migration run, which got changed in the meantime.
  * This is done by specifying a highwater field, which is compared with the
  * last time, the migration got executed (originalHighWater).
  */
 public function next()
 {
     $this->currentSourceIds = NULL;
     $this->currentRow = NULL;
     $source_configuration = $this->migration->get('source');
     // In order to find the next row we want to process, we ask the source
     // plugin for the next possible row.
     while (!isset($this->currentRow) && $this->getIterator()->valid()) {
         $row_data = $this->getIterator()->current() + $source_configuration;
         $this->getIterator()->next();
         $row = new Row($row_data, $this->migration->getSourcePlugin()->getIds(), $this->migration->get('destinationIds'));
         // Populate the source key for this row.
         $this->currentSourceIds = $row->getSourceIdValues();
         // Pick up the existing map row, if any, unless getNextRow() did it.
         if (!$this->mapRowAdded && ($id_map = $this->idMap->getRowBySource($this->currentSourceIds))) {
             $row->setIdMap($id_map);
         }
         // In case we have specified an ID list, but the ID given by the source is
         // not in there, we skip the row.
         $id_in_the_list = $this->idList && in_array(reset($this->currentSourceIds), $this->idList);
         if ($this->idList && !$id_in_the_list) {
             continue;
         }
         // Preparing the row gives source plugins the chance to skip.
         if ($this->prepareRow($row) === FALSE) {
             continue;
         }
         // Check whether the row needs processing.
         // 1. Explicitly specified IDs.
         // 2. This row has not been imported yet.
         // 3. Explicitly set to update.
         // 4. The row is newer than the current highwater mark.
         // 5. If no such property exists then try by checking the hash of the row.
         if ($id_in_the_list || !$row->getIdMap() || $row->needsUpdate() || $this->aboveHighwater($row) || $this->rowChanged($row)) {
             $this->currentRow = $row->freezeSource();
         }
     }
 }
Example #16
0
 /**
  * {@inheritdoc}
  */
 public function deleteBulk(array $source_id_values)
 {
     // If we have a single-column key, we can shortcut it.
     if (count($this->migration->getSourcePlugin()->getIds()) == 1) {
         $sourceids = array();
         foreach ($source_id_values as $source_id) {
             $sourceids[] = $source_id;
         }
         $this->getDatabase()->delete($this->mapTableName())->condition('sourceid1', $sourceids, 'IN')->execute();
         $this->getDatabase()->delete($this->messageTableName())->condition('sourceid1', $sourceids, 'IN')->execute();
     } else {
         foreach ($source_id_values as $source_id) {
             $map_query = $this->getDatabase()->delete($this->mapTableName());
             $message_query = $this->getDatabase()->delete($this->messageTableName());
             $count = 1;
             foreach ($source_id as $key_value) {
                 $map_query->condition('sourceid' . $count, $key_value);
                 $message_query->condition('sourceid' . $count++, $key_value);
             }
             $map_query->execute();
             $message_query->execute();
         }
     }
 }
 /**
  * Manipulate file fields with any per field type processing.
  *
  * @param string $field_name
  *   The field we're processing.
  * @param array $field_data
  *   The an array of field type data from the source.
  * @param \Drupal\migrate\Entity\MigrationInterface $migration
  *   The migration entity.
  */
 protected function processFileField($field_name, $field_data, MigrationInterface $migration)
 {
     $process = ['plugin' => 'd6_cck_file', 'source' => [$field_name, $field_name . '_list', $field_name . '_data']];
     $migration->mergeProcessOfProperty($field_name, $process);
 }
Example #18
0
 /**
  * Helper method to create an entity revision destination with mock services.
  *
  * @see \Drupal\Tests\migrate\Unit\Destination\EntityRevision
  *
  * @param $configuration
  *   Configuration for the destination.
  * @param string $plugin_id
  *   The plugin id.
  * @param array $plugin_definition
  *   The plugin definition.
  *
  * @return \Drupal\Tests\migrate\Unit\destination\EntityRevision
  *   Mocked destination.
  */
 protected function getEntityRevisionDestination(array $configuration = [], $plugin_id = 'entity_revision', array $plugin_definition = [])
 {
     return new EntityRevision($configuration, $plugin_id, $plugin_definition, $this->migration->reveal(), $this->storage->reveal(), [], $this->entityManager->reveal(), $this->fieldTypeManager->reveal());
 }
Example #19
0
 /**
  * {@inheritdoc}
  */
 public function processCckFieldValues(MigrationInterface $migration, $field_name, $data)
 {
     $process = ['plugin' => 'iterator', 'source' => $field_name, 'process' => ['target_id' => 'fid', 'alt' => 'alt', 'title' => 'title', 'width' => 'width', 'height' => 'height']];
     $migration->mergeProcessOfProperty($field_name, $process);
 }
Example #20
0
 /**
  * Class constructor.
  *
  * @param \Drupal\migrate\Entity\MigrationInterface $migration
  *   The migration entity.
  * @param \Drupal\migrate\MigrateExecutable $migrate_executable
  *   The migration executable.
  */
 public function __construct(MigrationInterface $migration, MigrateExecutable $migrate_executable)
 {
     $this->migration = $migration;
     $this->migrateExecutable = $migrate_executable;
     $configuration = $migration->get('source');
     if (!empty($configuration['cache_counts'])) {
         $this->cacheCounts = TRUE;
     }
     if (!empty($configuration['skip_count'])) {
         $this->skipCount = TRUE;
     }
     if (!empty($configuration['cache_key'])) {
         $this->cacheKey = $configuration['cache_key'];
     }
     if (!empty($configuration['track_changes'])) {
         $this->trackChanges = $configuration['track_changes'];
     }
 }
Example #21
0
 /**
  * {@inheritdoc}
  */
 public function processCckFieldValues(MigrationInterface $migration, $field_name, $data)
 {
     $process = array('plugin' => 'iterator', 'source' => $field_name, 'process' => array('target_id' => 'tid'));
     $migration->setProcessOfProperty($field_name, $process);
 }
 /**
  * Passes messages through to the map class.
  *
  * @param string $message
  *   The message to record.
  * @param int $level
  *   (optional) Message severity (defaults to MESSAGE_ERROR).
  */
 public function saveMessage($message, $level = MigrationInterface::MESSAGE_ERROR)
 {
     $this->migration->getIdMap()->saveMessage($this->sourceIdValues, $message, $level);
 }
Example #23
0
 /**
  * {@inheritdoc}
  */
 public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL)
 {
     list($entity_type_id) = explode('__', $migration->id());
     return new static($configuration, $plugin_id, $plugin_definition, $migration, $container->get('entity.manager')->getStorage($entity_type_id), array_keys($container->get('entity.manager')->getBundleInfo($entity_type_id)), $container->get('entity.manager'), $container->get('plugin.manager.field.field_type'), $container->get('password'));
 }
Example #24
0
 /**
  * {@inheritdoc}
  */
 public function processCckFieldValues(MigrationInterface $migration, $field_name, $data)
 {
     $process = ['plugin' => 'iterator', 'source' => $field_name, 'process' => ['target_id' => 'fid', 'display' => 'display', 'description' => 'description']];
     $migration->mergeProcessOfProperty($field_name, $process);
 }
Example #25
0
 /**
  * {@inheritdoc}
  */
 public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL)
 {
     $migration_configuration['migration'][] = $migration->id();
     return new static($configuration, $plugin_id, $plugin_definition, $container->get('plugin.manager.migrate.process')->createInstance('migration', $migration_configuration, $migration), $container->get('plugin.manager.menu.link'), $container->get('entity.manager')->getStorage('menu_link_content'));
 }
Example #26
0
 /**
  * Manipulate link fields with any per field type processing.
  *
  * @param string $field_name
  *   The field we're processing.
  * @param array $field_data
  *   The an array of field type data from the source.
  * @param \Drupal\migrate\Entity\MigrationInterface $migration
  *   The migration entity.
  */
 protected function processLinkField($field_name, $field_data, MigrationInterface $migration)
 {
     // Specifically process the link field until core is fixed.
     // @see https://www.drupal.org/node/2235457
     $process = ['plugin' => 'd6_cck_link', 'source' => [$field_name, $field_name . '_title', $field_name . '_attributes']];
     $migration->mergeProcessOfProperty($field_name, $process);
 }
Example #27
0
 /**
  * {@inheritdoc}
  */
 public function processCckFieldValues(MigrationInterface $migration, $field_name, $data)
 {
     $process = ['plugin' => 'd6_cck_file', 'source' => [$field_name, $field_name . '_list', $field_name . '_data']];
     $migration->mergeProcessOfProperty($field_name, $process);
 }
Example #28
0
 /**
  * {@inheritdoc}
  */
 public function processCckFieldValues(MigrationInterface $migration, $field_name, $data)
 {
     $process = array(array('plugin' => 'iterator', 'source' => $field_name, 'process' => ['value' => 'value', 'format' => [['plugin' => 'static_map', 'bypass' => TRUE, 'source' => 'format', 'map' => [0 => NULL]], ['plugin' => 'skip_on_empty', 'method' => 'process'], ['plugin' => 'migration', 'migration' => 'd6_filter_format', 'source' => 'format']]]));
     $migration->setProcessOfProperty($field_name, $process);
 }