Mercurial > hg > isophonics-drupal-site
comparison modules/contrib/migrate_tools/migrate_tools.drush.inc @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
1 <?php | |
2 | |
3 /** | |
4 * @file | |
5 * Command-line tools to aid performing and developing migrations. | |
6 */ | |
7 | |
8 use Drupal\Component\Plugin\Exception\PluginException; | |
9 use Drupal\Component\Plugin\Exception\PluginNotFoundException; | |
10 use Drupal\Component\Utility\Unicode; | |
11 use Drupal\Core\Database\ConnectionNotDefinedException; | |
12 use Drupal\migrate\Exception\RequirementsException; | |
13 use Drupal\migrate\Plugin\MigrationInterface; | |
14 use Drupal\migrate_tools\MigrateExecutable; | |
15 use Drupal\migrate_tools\DrushLogMigrateMessage; | |
16 use Drupal\Core\Datetime\DateFormatter; | |
17 | |
18 /** | |
19 * Implements hook_drush_command(). | |
20 */ | |
21 function migrate_tools_drush_command() { | |
22 $items['migrate-status'] = [ | |
23 'description' => 'List all migrations with current status.', | |
24 'options' => [ | |
25 'group' => 'Name of the migration group to list', | |
26 'names-only' => 'Only return names, not all the details (faster)', | |
27 ], | |
28 'arguments' => [ | |
29 'migration' => 'Restrict to a comma-separated list of migrations. Optional', | |
30 ], | |
31 'examples' => [ | |
32 'migrate-status' => 'Retrieve status for all migrations', | |
33 'migrate-status --group=beer' => 'Retrieve status for all migrations in a given group', | |
34 'migrate-status BeerTerm,BeerNode' => 'Retrieve status for specific migrations', | |
35 ], | |
36 'drupal dependencies' => ['migrate_tools'], | |
37 'aliases' => ['ms'], | |
38 ]; | |
39 | |
40 $items['migrate-import'] = [ | |
41 'description' => 'Perform one or more migration processes.', | |
42 'options' => [ | |
43 'all' => 'Process all migrations.', | |
44 'group' => 'Name of the migration group to import', | |
45 'limit' => 'Limit on the number of items to process in each migration', | |
46 'feedback' => 'Frequency of progress messages, in items processed', | |
47 'idlist' => 'Comma-separated list of IDs to import', | |
48 'update' => ' In addition to processing unprocessed items from the source, update previously-imported items with the current data', | |
49 'force' => 'Force an operation to run, even if all dependencies are not satisfied', | |
50 'execute-dependencies' => 'Execute all dependent migrations first.', | |
51 ], | |
52 'arguments' => [ | |
53 'migration' => 'Name of migration(s) to import. Delimit multiple using commas.', | |
54 ], | |
55 'examples' => [ | |
56 'migrate-import --all' => 'Perform all migrations', | |
57 'migrate-import --group=beer' => 'Import all migrations in the beer group', | |
58 'migrate-import BeerTerm,BeerNode' => 'Import new terms and nodes', | |
59 'migrate-import BeerUser --limit=2' => 'Import no more than 2 users', | |
60 'migrate-import BeerUser --idlist=5' => 'Import the user record with source ID 5', | |
61 ], | |
62 'drupal dependencies' => ['migrate_tools'], | |
63 'aliases' => ['mi'], | |
64 ]; | |
65 | |
66 $items['migrate-rollback'] = array( | |
67 'description' => 'Rollback one or more migrations.', | |
68 'options' => array( | |
69 'all' => 'Process all migrations.', | |
70 'group' => 'Name of the migration group to rollback', | |
71 'feedback' => 'Frequency of progress messages, in items processed', | |
72 ), | |
73 'arguments' => array( | |
74 'migration' => 'Name of migration(s) to rollback. Delimit multiple using commas.', | |
75 ), | |
76 'examples' => array( | |
77 'migrate-rollback --all' => 'Perform all migrations', | |
78 'migrate-rollback --group=beer' => 'Rollback all migrations in the beer group', | |
79 'migrate-rollback BeerTerm,BeerNode' => 'Rollback imported terms and nodes', | |
80 ), | |
81 'drupal dependencies' => array('migrate_tools'), | |
82 'aliases' => array('mr'), | |
83 ); | |
84 | |
85 $items['migrate-stop'] = [ | |
86 'description' => 'Stop an active migration operation.', | |
87 'arguments' => [ | |
88 'migration' => 'Name of migration to stop', | |
89 ], | |
90 'drupal dependencies' => ['migrate_tools'], | |
91 'aliases' => ['mst'], | |
92 ]; | |
93 | |
94 $items['migrate-reset-status'] = [ | |
95 'description' => 'Reset a active migration\'s status to idle.', | |
96 'arguments' => [ | |
97 'migration' => 'Name of migration to reset', | |
98 ], | |
99 'drupal dependencies' => ['migrate_tools'], | |
100 'aliases' => ['mrs'], | |
101 ]; | |
102 | |
103 $items['migrate-messages'] = [ | |
104 'description' => 'View any messages associated with a migration.', | |
105 'arguments' => [ | |
106 'migration' => 'Name of the migration', | |
107 ], | |
108 'options' => [ | |
109 'csv' => 'Export messages as a CSV' | |
110 ], | |
111 'examples' => [ | |
112 'migrate-messages MyNode' => 'Show all messages for the MyNode migration', | |
113 ], | |
114 'drupal dependencies' => ['migrate_tools'], | |
115 'aliases' => ['mmsg'], | |
116 ]; | |
117 | |
118 $items['migrate-fields-source'] = [ | |
119 'description' => 'List the fields available for mapping in a source.', | |
120 'arguments' => [ | |
121 'migration' => 'Name of the migration', | |
122 ], | |
123 'examples' => [ | |
124 'migrate-fields-source my_node' => 'List fields for the source in the my_node migration', | |
125 ], | |
126 'drupal dependencies' => ['migrate_tools'], | |
127 'aliases' => ['mfs'], | |
128 ]; | |
129 | |
130 return $items; | |
131 } | |
132 | |
133 /** | |
134 * @param string $migration_names | |
135 */ | |
136 function drush_migrate_tools_migrate_status($migration_names = '') { | |
137 $group_name = drush_get_option('group'); | |
138 $names_only = drush_get_option('names-only'); | |
139 | |
140 $migrations = drush_migrate_tools_migration_list($group_name, $migration_names); | |
141 | |
142 $table = []; | |
143 // Take it one group at a time, listing the migrations within each group. | |
144 foreach ($migrations as $group_id => $migration_list) { | |
145 if ($names_only) { | |
146 $table[] = [ | |
147 dt('Group: @name', array('@name' => $group_id)) | |
148 ]; | |
149 } | |
150 else { | |
151 $table[] = [ | |
152 dt('Group: @name', array('@name' => $group_id)), | |
153 dt('Status'), | |
154 dt('Total'), | |
155 dt('Imported'), | |
156 dt('Unprocessed'), | |
157 dt('Last imported'), | |
158 ]; | |
159 } | |
160 foreach ($migration_list as $migration_id => $migration) { | |
161 try { | |
162 $map = $migration->getIdMap(); | |
163 $imported = $map->importedCount(); | |
164 $source_plugin = $migration->getSourcePlugin(); | |
165 } | |
166 catch (Exception $e) { | |
167 drush_log(dt('Failure retrieving information on @migration: @message', | |
168 ['@migration' => $migration_id, '@message' => $e->getMessage()])); | |
169 continue; | |
170 } | |
171 try { | |
172 $source_rows = $source_plugin->count(); | |
173 // -1 indicates uncountable sources. | |
174 if ($source_rows == -1) { | |
175 $source_rows = dt('N/A'); | |
176 $unprocessed = dt('N/A'); | |
177 } | |
178 else { | |
179 $unprocessed = $source_rows - $map->processedCount(); | |
180 } | |
181 } | |
182 catch (Exception $e) { | |
183 drush_print($e->getMessage()); | |
184 drush_log(dt('Could not retrieve source count from @migration: @message', | |
185 ['@migration' => $migration_id, '@message' => $e->getMessage()])); | |
186 $source_rows = dt('N/A'); | |
187 $unprocessed = dt('N/A'); | |
188 } | |
189 | |
190 if ($names_only) { | |
191 $table[] = [$migration_id]; | |
192 } | |
193 else { | |
194 $status = $migration->getStatusLabel(); | |
195 $migrate_last_imported_store = \Drupal::keyValue('migrate_last_imported'); | |
196 $last_imported = $migrate_last_imported_store->get($migration->id(), FALSE); | |
197 if ($last_imported) { | |
198 /** @var DateFormatter $date_formatter */ | |
199 $date_formatter = \Drupal::service('date.formatter'); | |
200 $last_imported = $date_formatter->format($last_imported / 1000, | |
201 'custom', 'Y-m-d H:i:s'); | |
202 } | |
203 else { | |
204 $last_imported = ''; | |
205 } | |
206 $table[] = [$migration_id, $status, $source_rows, $imported, $unprocessed, $last_imported]; | |
207 } | |
208 } | |
209 } | |
210 drush_print_table($table); | |
211 } | |
212 | |
213 /** | |
214 * @param string $migration_names | |
215 */ | |
216 function drush_migrate_tools_migrate_import($migration_names = '') { | |
217 $group_name = drush_get_option('group'); | |
218 $all = drush_get_option('all'); | |
219 $options = []; | |
220 if (!$all && !$group_name && !$migration_names) { | |
221 drush_set_error('MIGRATE_ERROR', dt('You must specify --all, --group, or one or more migration names separated by commas')); | |
222 return; | |
223 } | |
224 | |
225 foreach (['limit', 'feedback', 'idlist', 'update', 'force'] as $option) { | |
226 if (drush_get_option($option)) { | |
227 $options[$option] = drush_get_option($option); | |
228 } | |
229 } | |
230 | |
231 $migrations = drush_migrate_tools_migration_list($group_name, $migration_names); | |
232 | |
233 // Take it one group at a time, importing the migrations within each group. | |
234 foreach ($migrations as $group_id => $migration_list) { | |
235 array_walk($migration_list, '_drush_migrate_tools_execute_migration', $options); | |
236 } | |
237 } | |
238 | |
239 /** | |
240 * Executes a single migration. If the --execute-dependencies option was given, | |
241 * the migration's dependencies will also be executed first. | |
242 * | |
243 * @param \Drupal\migrate\Plugin\MigrationInterface $migration | |
244 * The migration to execute. | |
245 * @param string $migration_id | |
246 * The migration ID (not used, just an artifact of array_walk()). | |
247 * @param array $options | |
248 * Additional options for the migration. | |
249 */ | |
250 function _drush_migrate_tools_execute_migration(MigrationInterface $migration, $migration_id, array $options = []) { | |
251 $log = new DrushLogMigrateMessage(); | |
252 | |
253 if (drush_get_option('execute-dependencies')) { | |
254 if ($required_IDS = $migration->get('requirements')) { | |
255 $manager = \Drupal::service('plugin.manager.config_entity_migration'); | |
256 $required_migrations = $manager->createInstances($required_IDS); | |
257 $dependency_options = array_merge($options, ['is_dependency' => TRUE]); | |
258 array_walk($required_migrations, __FUNCTION__, $dependency_options); | |
259 } | |
260 } | |
261 if ($options['force']) { | |
262 $migration->set('requirements', []); | |
263 } | |
264 if ($options['update']) { | |
265 $migration->getIdMap()->prepareUpdate(); | |
266 } | |
267 $executable = new MigrateExecutable($migration, $log, $options); | |
268 // drush_op() provides --simulate support | |
269 drush_op(array($executable, 'import')); | |
270 } | |
271 | |
272 /** | |
273 * @param string $migration_names | |
274 */ | |
275 function drush_migrate_tools_migrate_rollback($migration_names = '') { | |
276 $group_name = drush_get_option('group'); | |
277 $all = drush_get_option('all'); | |
278 $options = []; | |
279 if (!$all && !$group_name && !$migration_names) { | |
280 drush_set_error('MIGRATE_ERROR', dt('You must specify --all, --group, or one or more migration names separated by commas')); | |
281 return; | |
282 } | |
283 | |
284 if (drush_get_option('feedback')) { | |
285 $options['feedback'] = drush_get_option('feedback'); | |
286 } | |
287 | |
288 $log = new DrushLogMigrateMessage(); | |
289 | |
290 $migrations = drush_migrate_tools_migration_list($group_name, $migration_names); | |
291 | |
292 // Take it one group at a time, rolling back the migrations within each group. | |
293 foreach ($migrations as $group_id => $migration_list) { | |
294 // Roll back in reverse order. | |
295 $migration_list = array_reverse($migration_list); | |
296 foreach ($migration_list as $migration_id => $migration) { | |
297 $executable = new MigrateExecutable($migration, $log, $options); | |
298 // drush_op() provides --simulate support. | |
299 drush_op(array($executable, 'rollback')); | |
300 } | |
301 } | |
302 } | |
303 | |
304 /** | |
305 * @param string $migration_id | |
306 */ | |
307 function drush_migrate_tools_migrate_stop($migration_id = '') { | |
308 /** @var MigrationInterface $migration */ | |
309 $migration = \Drupal::service('plugin.manager.migration')->createInstance($migration_id); | |
310 if ($migration) { | |
311 $status = $migration->getStatus(); | |
312 switch ($status) { | |
313 case MigrationInterface::STATUS_IDLE: | |
314 drush_log(dt('Migration @id is idle', ['@id' => $migration_id]), 'warning'); | |
315 break; | |
316 case MigrationInterface::STATUS_DISABLED: | |
317 drush_log(dt('Migration @id is disabled', ['@id' => $migration_id]), 'warning'); | |
318 break; | |
319 case MigrationInterface::STATUS_STOPPING: | |
320 drush_log(dt('Migration @id is already stopping', ['@id' => $migration_id]), 'warning'); | |
321 break; | |
322 default: | |
323 $migration->interruptMigration(MigrationInterface::RESULT_STOPPED); | |
324 drush_log(dt('Migration @id requested to stop', ['@id' => $migration_id]), 'success'); | |
325 break; | |
326 } | |
327 } | |
328 else { | |
329 drush_log(dt('Migration @id does not exist', ['@id' => $migration_id]), 'error'); | |
330 } | |
331 } | |
332 | |
333 /** | |
334 * @param string $migration_id | |
335 */ | |
336 function drush_migrate_tools_migrate_reset_status($migration_id = '') { | |
337 /** @var MigrationInterface $migration */ | |
338 $migration = \Drupal::service('plugin.manager.migration')->createInstance($migration_id); | |
339 if ($migration) { | |
340 $status = $migration->getStatus(); | |
341 if ($status == MigrationInterface::STATUS_IDLE) { | |
342 drush_log(dt('Migration @id is already Idle', ['@id' => $migration_id]), 'warning'); | |
343 } | |
344 else { | |
345 $migration->setStatus(MigrationInterface::STATUS_IDLE); | |
346 drush_log(dt('Migration @id reset to Idle', ['@id' => $migration_id]), 'status'); | |
347 } | |
348 } | |
349 else { | |
350 drush_log(dt('Migration @id does not exist', ['@id' => $migration_id]), 'error'); | |
351 } | |
352 } | |
353 | |
354 /** | |
355 * @param string $migration_id | |
356 */ | |
357 function drush_migrate_tools_migrate_messages($migration_id) { | |
358 /** @var MigrationInterface $migration */ | |
359 $migration = \Drupal::service('plugin.manager.migration')->createInstance($migration_id); | |
360 if ($migration) { | |
361 $map = $migration->getIdMap(); | |
362 $first = TRUE; | |
363 $table = []; | |
364 foreach ($map->getMessageIterator() as $row) { | |
365 unset($row->msgid); | |
366 if ($first) { | |
367 // @todo: Ideally, replace sourceid* with source key names. Or, should | |
368 // getMessageIterator() do that? | |
369 foreach ($row as $column => $value) { | |
370 $table[0][] = $column; | |
371 } | |
372 $first = FALSE; | |
373 } | |
374 $table[] = (array)$row; | |
375 } | |
376 if (empty($table)) { | |
377 drush_log(dt('No messages for this migration'), 'status'); | |
378 } | |
379 else { | |
380 if (drush_get_option('csv')) { | |
381 foreach ($table as $row) { | |
382 fputcsv(STDOUT, $row); | |
383 } | |
384 } | |
385 else { | |
386 $widths = []; | |
387 foreach ($table[0] as $header) { | |
388 $widths[] = strlen($header) + 1; | |
389 } | |
390 drush_print_table($table, TRUE, $widths); | |
391 } | |
392 } | |
393 } | |
394 else { | |
395 drush_log(dt('Migration @id does not exist', ['@id' => $migration_id]), 'error'); | |
396 } | |
397 } | |
398 | |
399 /** | |
400 * @param string $migration_id | |
401 */ | |
402 function drush_migrate_tools_migrate_fields_source($migration_id) { | |
403 /** @var MigrationInterface $migration */ | |
404 $migration = \Drupal::service('plugin.manager.migration')->createInstance($migration_id); | |
405 if ($migration) { | |
406 $source = $migration->getSourcePlugin(); | |
407 $table = []; | |
408 foreach ($source->fields() as $machine_name => $description) { | |
409 $table[] = [strip_tags($description), $machine_name]; | |
410 } | |
411 drush_print_table($table); | |
412 } | |
413 else { | |
414 drush_log(dt('Migration @id does not exist', ['@id' => $migration_id]), 'error'); | |
415 } | |
416 } | |
417 | |
418 /** | |
419 * Retrieve a list of active migrations. | |
420 * | |
421 * @param string $group_id | |
422 * Group machine name - if present, return only migrations in this group. | |
423 * @param string $migration_ids | |
424 * Comma-separated list of migrations - if present, return only these migrations. | |
425 * | |
426 * @return MigrationInterface[][] | |
427 * An array keyed by migration group, each value containing an array of migrations. | |
428 */ | |
429 function drush_migrate_tools_migration_list($group_id = '', $migration_ids = '') { | |
430 if (!empty($migration_ids)) { | |
431 $migration_ids = explode(',', Unicode::strtolower($migration_ids)); | |
432 } | |
433 else { | |
434 $migration_ids = []; | |
435 } | |
436 | |
437 $manager = \Drupal::service('plugin.manager.config_entity_migration'); | |
438 $plugins = $manager->createInstances([]); | |
439 $migrations = []; | |
440 foreach ($plugins as $id => $migration) { | |
441 $configured_group_id = $migration->get('migration_group'); | |
442 if (empty($configured_group_id)) { | |
443 $configured_group_id = 'default'; | |
444 } | |
445 if (empty($group_id) || $group_id == $configured_group_id) { | |
446 if (empty($migration_ids) || in_array(Unicode::strtolower($id), $migration_ids)) { | |
447 $migrations[$configured_group_id][$id] = $migration; | |
448 } | |
449 } | |
450 } | |
451 return $migrations; | |
452 } |