Backup of db before drupal security update
[yaffs-website] / web / core / modules / migrate_drupal_ui / src / Form / MigrateUpgradeForm.php
1 <?php
2
3 namespace Drupal\migrate_drupal_ui\Form;
4
5 use Drupal\Core\Datetime\DateFormatterInterface;
6 use Drupal\Core\Form\ConfirmFormBase;
7 use Drupal\Core\Form\FormStateInterface;
8 use Drupal\Core\Render\RendererInterface;
9 use Drupal\Core\State\StateInterface;
10 use Drupal\Core\Url;
11 use Drupal\migrate\Plugin\MigrationPluginManagerInterface;
12 use Drupal\migrate_drupal_ui\Batch\MigrateUpgradeImportBatch;
13 use Drupal\migrate_drupal\MigrationConfigurationTrait;
14 use Symfony\Component\DependencyInjection\ContainerInterface;
15
16 /**
17  * Defines a multi-step form for performing direct site upgrades.
18  */
19 class MigrateUpgradeForm extends ConfirmFormBase {
20
21   use MigrationConfigurationTrait;
22
23   /**
24    * Mapping of known migrations and their source and destination modules.
25    *
26    * @todo https://www.drupal.org/node/2569805 Hardcoding this information is
27    *   not robust - the migrations themselves should hold the necessary
28    *   information.
29    *
30    * @var array[]
31    */
32   protected $moduleUpgradePaths = [
33     'action_settings' => [
34       'source_module' => 'system',
35       'destination_module' => 'action',
36     ],
37     'd6_aggregator_feed' => [
38       'source_module' => 'aggregator',
39       'destination_module' => 'aggregator',
40     ],
41     'd6_aggregator_item' => [
42       'source_module' => 'aggregator',
43       'destination_module' => 'aggregator',
44     ],
45     'd6_aggregator_settings' => [
46       'source_module' => 'aggregator',
47       'destination_module' => 'aggregator',
48     ],
49     'd7_aggregator_feed' => [
50       'source_module' => 'aggregator',
51       'destination_module' => 'aggregator',
52     ],
53     'd7_aggregator_item' => [
54       'source_module' => 'aggregator',
55       'destination_module' => 'aggregator',
56     ],
57     'd7_aggregator_settings' => [
58       'source_module' => 'aggregator',
59       'destination_module' => 'aggregator',
60     ],
61     'd7_blocked_ips' => [
62       'source_module' => 'system',
63       'destination_module' => 'ban',
64     ],
65     'd6_block' => [
66       'source_module' => 'block',
67       'destination_module' => 'block',
68     ],
69     'd7_block' => [
70       'source_module' => 'block',
71       'destination_module' => 'block',
72     ],
73     'block_content_entity_form_display' => [
74       'source_module' => 'block',
75       'destination_module' => 'block_content',
76     ],
77     'block_content_entity_display' => [
78       'source_module' => 'block',
79       'destination_module' => 'block_content',
80     ],
81     'block_content_body_field' => [
82       'source_module' => 'block',
83       'destination_module' => 'block_content',
84     ],
85     'block_content_type' => [
86       'source_module' => 'block',
87       'destination_module' => 'block_content',
88     ],
89     'd6_custom_block' => [
90       'source_module' => 'block',
91       'destination_module' => 'block_content',
92     ],
93     'd7_custom_block' => [
94       'source_module' => 'block',
95       'destination_module' => 'block_content',
96     ],
97     'd6_book' => [
98       'source_module' => 'book',
99       'destination_module' => 'book',
100     ],
101     'd6_book_settings' => [
102       'source_module' => 'book',
103       'destination_module' => 'book',
104     ],
105     'd6_comment' => [
106       'source_module' => 'comment',
107       'destination_module' => 'comment',
108     ],
109     'd6_comment_entity_display' => [
110       'source_module' => 'comment',
111       'destination_module' => 'comment',
112     ],
113     'd6_comment_entity_form_display' => [
114       'source_module' => 'comment',
115       'destination_module' => 'comment',
116     ],
117     'd6_comment_entity_form_display_subject' => [
118       'source_module' => 'comment',
119       'destination_module' => 'comment',
120     ],
121     'd6_comment_field' => [
122       'source_module' => 'comment',
123       'destination_module' => 'comment',
124     ],
125     'd6_comment_field_instance' => [
126       'source_module' => 'comment',
127       'destination_module' => 'comment',
128     ],
129     'd6_comment_type' => [
130       'source_module' => 'comment',
131       'destination_module' => 'comment',
132     ],
133     'd7_comment' => [
134       'source_module' => 'comment',
135       'destination_module' => 'comment',
136     ],
137     'd7_comment_entity_display' => [
138       'source_module' => 'comment',
139       'destination_module' => 'comment',
140     ],
141     'd7_comment_entity_form_display' => [
142       'source_module' => 'comment',
143       'destination_module' => 'comment',
144     ],
145     'd7_comment_entity_form_display_subject' => [
146       'source_module' => 'comment',
147       'destination_module' => 'comment',
148     ],
149     'd7_comment_field' => [
150       'source_module' => 'comment',
151       'destination_module' => 'comment',
152     ],
153     'd7_comment_field_instance' => [
154       'source_module' => 'comment',
155       'destination_module' => 'comment',
156     ],
157     'd7_comment_type' => [
158       'source_module' => 'comment',
159       'destination_module' => 'comment',
160     ],
161     'contact_category' => [
162       'source_module' => 'contact',
163       'destination_module' => 'contact',
164     ],
165     'd6_contact_settings' => [
166       'source_module' => 'contact',
167       'destination_module' => 'contact',
168     ],
169     'd7_contact_settings' => [
170       'source_module' => 'contact',
171       'destination_module' => 'contact',
172     ],
173     'd6_dblog_settings' => [
174       'source_module' => 'dblog',
175       'destination_module' => 'dblog',
176     ],
177     'd7_dblog_settings' => [
178       'source_module' => 'dblog',
179       'destination_module' => 'dblog',
180     ],
181     'default_language' => [
182       'source_module' => 'locale',
183       'destination_module' => 'language',
184     ],
185     'd6_field' => [
186       'source_module' => 'content',
187       'destination_module' => 'field',
188     ],
189     'd6_field_formatter_settings' => [
190       'source_module' => 'content',
191       'destination_module' => 'field',
192     ],
193     'd6_field_instance' => [
194       'source_module' => 'content',
195       'destination_module' => 'field',
196     ],
197     'd6_field_instance_widget_settings' => [
198       'source_module' => 'content',
199       'destination_module' => 'field',
200     ],
201     'd7_field' => [
202       'source_module' => 'field',
203       'destination_module' => 'field',
204     ],
205     'd7_field_formatter_settings' => [
206       'source_module' => 'field',
207       'destination_module' => 'field',
208     ],
209     'd7_field_instance' => [
210       'source_module' => 'field',
211       'destination_module' => 'field',
212     ],
213     'd7_field_instance_widget_settings' => [
214       'source_module' => 'field',
215       'destination_module' => 'field',
216     ],
217     'd7_view_modes' => [
218       'source_module' => 'field',
219       'destination_module' => 'field',
220     ],
221     'd6_file' => [
222       'source_module' => 'system',
223       'destination_module' => 'file',
224     ],
225     'file_settings' => [
226       'source_module' => 'system',
227       'destination_module' => 'file',
228     ],
229     'd6_upload' => [
230       'source_module' => 'upload',
231       'destination_module' => 'file',
232     ],
233     'd6_upload_entity_display' => [
234       'source_module' => 'upload',
235       'destination_module' => 'file',
236     ],
237     'd6_upload_entity_form_display' => [
238       'source_module' => 'upload',
239       'destination_module' => 'file',
240     ],
241     'd6_upload_field' => [
242       'source_module' => 'upload',
243       'destination_module' => 'file',
244     ],
245     'd6_upload_field_instance' => [
246       'source_module' => 'upload',
247       'destination_module' => 'file',
248     ],
249     'd7_file' => [
250       'source_module' => 'file',
251       'destination_module' => 'file',
252     ],
253     'd6_filter_format' => [
254       'source_module' => 'filter',
255       'destination_module' => 'filter',
256     ],
257     'd7_filter_format' => [
258       'source_module' => 'filter',
259       'destination_module' => 'filter',
260     ],
261     'd7_filter_settings' => [
262       'source_module' => 'filter',
263       'destination_module' => 'filter',
264     ],
265     'd6_forum_settings' => [
266       'source_module' => 'forum',
267       'destination_module' => 'forum',
268     ],
269     'd7_forum_settings' => [
270       'source_module' => 'forum',
271       'destination_module' => 'forum',
272     ],
273     'd7_global_theme_settings' => [
274       'source_module' => 'system',
275       'destination_module' => 'system',
276     ],
277     'd6_imagecache_presets' => [
278       'source_module' => 'imagecache',
279       'destination_module' => 'image',
280     ],
281     'd7_image_settings' => [
282       'source_module' => 'image',
283       'destination_module' => 'image',
284     ],
285     'd7_image_styles' => [
286       'source_module' => 'image',
287       'destination_module' => 'image',
288     ],
289     'd6_language_content_settings' => [
290       'source_module' => 'locale',
291       'destination_module' => 'language',
292     ],
293     'd7_language_content_settings' => [
294       'source_module' => 'locale',
295       'destination_module' => 'language',
296     ],
297     'd6_language_negotiation_settings' => [
298       'source_module' => 'locale',
299       'destination_module' => 'language',
300     ],
301     'd7_language_negotiation_settings' => [
302       'source_module' => 'locale',
303       'destination_module' => 'language',
304     ],
305     'language_prefixes_and_domains' => [
306       'source_module' => 'locale',
307       'destination_module' => 'language',
308     ],
309     'd6_language_types' => [
310       'source_module' => 'locale',
311       'destination_module' => 'language',
312     ],
313     'language' => [
314       'source_module' => 'locale',
315       'destination_module' => 'language',
316     ],
317     'd7_language_types' => [
318       'source_module' => 'locale',
319       'destination_module' => 'language',
320     ],
321     'locale_settings' => [
322       'source_module' => 'locale',
323       'destination_module' => 'locale',
324     ],
325     'd6_menu_links' => [
326       'source_module' => 'menu',
327       'destination_module' => 'menu_link_content',
328     ],
329     'menu_settings' => [
330       'source_module' => 'menu',
331       'destination_module' => 'menu_ui',
332     ],
333     'd7_menu_links' => [
334       'source_module' => 'menu',
335       'destination_module' => 'menu_link_content',
336     ],
337     'd6_node' => [
338       'source_module' => 'node',
339       'destination_module' => 'node',
340     ],
341     'd6_node_translation' => [
342       'source_module' => 'translation',
343       'destination_module' => 'content_translation',
344     ],
345     'd6_node_revision' => [
346       'source_module' => 'node',
347       'destination_module' => 'node',
348     ],
349     'd6_node_setting_promote' => [
350       'source_module' => 'node',
351       'destination_module' => 'node',
352     ],
353     'd6_node_setting_status' => [
354       'source_module' => 'node',
355       'destination_module' => 'node',
356     ],
357     'd6_node_setting_sticky' => [
358       'source_module' => 'node',
359       'destination_module' => 'node',
360     ],
361     'd6_node_settings' => [
362       'source_module' => 'node',
363       'destination_module' => 'node',
364     ],
365     'd6_node_type' => [
366       'source_module' => 'node',
367       'destination_module' => 'node',
368     ],
369     'd6_view_modes' => [
370       'source_module' => 'node',
371       'destination_module' => 'node',
372     ],
373     'd7_node' => [
374       'source_module' => 'node',
375       'destination_module' => 'node',
376     ],
377     'd7_node_revision' => [
378       'source_module' => 'node',
379       'destination_module' => 'node',
380     ],
381     'd7_node_settings' => [
382       'source_module' => 'node',
383       'destination_module' => 'node',
384     ],
385     'd7_node_translation' => [
386       'source_module' => 'node',
387       'destination_module' => 'node',
388     ],
389     'd7_node_title_label' => [
390       'source_module' => 'node',
391       'destination_module' => 'node',
392     ],
393     'd7_node_type' => [
394       'source_module' => 'node',
395       'destination_module' => 'node',
396     ],
397     'd6_url_alias' => [
398       'source_module' => 'path',
399       'destination_module' => 'path',
400     ],
401     'd7_url_alias' => [
402       'source_module' => 'path',
403       'destination_module' => 'path',
404     ],
405     'search_page' => [
406       'source_module' => 'search',
407       'destination_module' => 'search',
408     ],
409     'd6_search_settings' => [
410       'source_module' => 'search',
411       'destination_module' => 'search',
412     ],
413     'd7_search_settings' => [
414       'source_module' => 'search',
415       'destination_module' => 'search',
416     ],
417     'd7_shortcut' => [
418       'source_module' => 'shortcut',
419       'destination_module' => 'shortcut',
420     ],
421     'd7_shortcut_set' => [
422       'source_module' => 'shortcut',
423       'destination_module' => 'shortcut',
424     ],
425     'd7_shortcut_set_users' => [
426       'source_module' => 'shortcut',
427       'destination_module' => 'shortcut',
428     ],
429     'd6_simpletest_settings' => [
430       'source_module' => 'simpletest',
431       'destination_module' => 'simpletest',
432     ],
433     'd7_simpletest_settings' => [
434       'source_module' => 'simpletest',
435       'destination_module' => 'simpletest',
436     ],
437     'statistics_settings' => [
438       'source_module' => 'statistics',
439       'destination_module' => 'statistics',
440     ],
441     'd6_syslog_settings' => [
442       'source_module' => 'syslog',
443       'destination_module' => 'syslog',
444     ],
445     'd7_syslog_settings' => [
446       'source_module' => 'syslog',
447       'destination_module' => 'syslog',
448     ],
449     'd6_date_formats' => [
450       'source_module' => 'system',
451       'destination_module' => 'system',
452     ],
453     'd6_system_cron' => [
454       'source_module' => 'system',
455       'destination_module' => 'system',
456     ],
457     'd6_system_date' => [
458       'source_module' => 'system',
459       'destination_module' => 'system',
460     ],
461     'd6_system_file' => [
462       'source_module' => 'system',
463       'destination_module' => 'system',
464     ],
465     'system_image' => [
466       'source_module' => 'system',
467       'destination_module' => 'system',
468     ],
469     'system_image_gd' => [
470       'source_module' => 'system',
471       'destination_module' => 'system',
472     ],
473     'system_logging' => [
474       'source_module' => 'system',
475       'destination_module' => 'system',
476     ],
477     'system_maintenance' => [
478       'source_module' => 'system',
479       'destination_module' => 'system',
480     ],
481     'd6_system_performance' => [
482       'source_module' => 'system',
483       'destination_module' => 'system',
484     ],
485     'system_rss' => [
486       'source_module' => 'system',
487       'destination_module' => 'system',
488     ],
489     'system_site' => [
490       'source_module' => 'system',
491       'destination_module' => 'system',
492     ],
493     'd7_system_authorize' => [
494       'source_module' => 'system',
495       'destination_module' => 'system',
496     ],
497     'd7_system_cron' => [
498       'source_module' => 'system',
499       'destination_module' => 'system',
500     ],
501     'd7_system_date' => [
502       'source_module' => 'system',
503       'destination_module' => 'system',
504     ],
505     'd7_system_file' => [
506       'source_module' => 'system',
507       'destination_module' => 'system',
508     ],
509     'd7_system_mail' => [
510       'source_module' => 'system',
511       'destination_module' => 'system',
512     ],
513     'd7_system_performance' => [
514       'source_module' => 'system',
515       'destination_module' => 'system',
516     ],
517     'd6_menu' => [
518       'source_module' => 'menu',
519       'destination_module' => 'system',
520     ],
521     'd7_menu' => [
522       'source_module' => 'menu',
523       'destination_module' => 'system',
524     ],
525     'taxonomy_settings' => [
526       'source_module' => 'taxonomy',
527       'destination_module' => 'taxonomy',
528     ],
529     'd6_taxonomy_term' => [
530       'source_module' => 'taxonomy',
531       'destination_module' => 'taxonomy',
532     ],
533     'd6_taxonomy_vocabulary' => [
534       'source_module' => 'taxonomy',
535       'destination_module' => 'taxonomy',
536     ],
537     'd6_term_node' => [
538       'source_module' => 'taxonomy',
539       'destination_module' => 'taxonomy',
540     ],
541     'd6_term_node_revision' => [
542       'source_module' => 'taxonomy',
543       'destination_module' => 'taxonomy',
544     ],
545     'd6_vocabulary_entity_display' => [
546       'source_module' => 'taxonomy',
547       'destination_module' => 'taxonomy',
548     ],
549     'd6_vocabulary_entity_form_display' => [
550       'source_module' => 'taxonomy',
551       'destination_module' => 'taxonomy',
552     ],
553     'd6_vocabulary_field' => [
554       'source_module' => 'taxonomy',
555       'destination_module' => 'taxonomy',
556     ],
557     'd6_vocabulary_field_instance' => [
558       'source_module' => 'taxonomy',
559       'destination_module' => 'taxonomy',
560     ],
561     'd7_taxonomy_term' => [
562       'source_module' => 'taxonomy',
563       'destination_module' => 'taxonomy',
564     ],
565     'd7_taxonomy_vocabulary' => [
566       'source_module' => 'taxonomy',
567       'destination_module' => 'taxonomy',
568     ],
569     'text_settings' => [
570       'source_module' => 'text',
571       'destination_module' => 'text',
572     ],
573     'd7_tracker_node' => [
574       'source_module' => 'tracker',
575       'destination_module' => 'tracker',
576     ],
577     'd7_tracker_settings' => [
578       'source_module' => 'tracker',
579       'destination_module' => 'tracker',
580     ],
581     'd7_tracker_user' => [
582       'source_module' => 'tracker',
583       'destination_module' => 'tracker',
584     ],
585     'update_settings' => [
586       'source_module' => 'update',
587       'destination_module' => 'update',
588     ],
589     'd6_profile_values' => [
590       'source_module' => 'profile',
591       'destination_module' => 'user',
592     ],
593     'd7_theme_settings' => [
594       'source_module' => 'system',
595       'destination_module' => 'system',
596     ],
597     'd6_user' => [
598       'source_module' => 'user',
599       'destination_module' => 'user',
600     ],
601     'd6_user_contact_settings' => [
602       'source_module' => 'user',
603       'destination_module' => 'user',
604     ],
605     'd6_user_mail' => [
606       'source_module' => 'user',
607       'destination_module' => 'user',
608     ],
609     'd6_user_picture_file' => [
610       'source_module' => 'user',
611       'destination_module' => 'user',
612     ],
613     'd6_user_role' => [
614       'source_module' => 'user',
615       'destination_module' => 'user',
616     ],
617     'd6_user_settings' => [
618       'source_module' => 'user',
619       'destination_module' => 'user',
620     ],
621     'd7_user' => [
622       'source_module' => 'user',
623       'destination_module' => 'user',
624     ],
625     'd7_user_flood' => [
626       'source_module' => 'user',
627       'destination_module' => 'user',
628     ],
629     'd7_user_mail' => [
630       'source_module' => 'user',
631       'destination_module' => 'user',
632     ],
633     'd7_user_role' => [
634       'source_module' => 'user',
635       'destination_module' => 'user',
636     ],
637     'user_picture_entity_display' => [
638       'source_module' => 'user',
639       'destination_module' => 'user',
640     ],
641     'user_picture_entity_form_display' => [
642       'source_module' => 'user',
643       'destination_module' => 'user',
644     ],
645     'user_picture_field' => [
646       'source_module' => 'user',
647       'destination_module' => 'user',
648     ],
649     'user_picture_field_instance' => [
650       'source_module' => 'user',
651       'destination_module' => 'user',
652     ],
653     'user_profile_entity_display' => [
654       'source_module' => 'profile',
655       'destination_module' => 'user',
656     ],
657     'user_profile_entity_form_display' => [
658       'source_module' => 'profile',
659       'destination_module' => 'user',
660     ],
661     'user_profile_field' => [
662       'source_module' => 'profile',
663       'destination_module' => 'user',
664     ],
665     'user_profile_field_instance' => [
666       'source_module' => 'profile',
667       'destination_module' => 'user',
668     ],
669     'd6_i18n_user_profile_field_instance' => [
670       'source_module' => 'i18n',
671       'destination_module' => 'user',
672     ],
673   ];
674
675   /**
676    * The state service.
677    *
678    * @var \Drupal\Core\State\StateInterface
679    */
680   protected $state;
681
682   /**
683    * The date formatter service.
684    *
685    * @var \Drupal\Core\Datetime\DateFormatterInterface
686    */
687   protected $dateFormatter;
688
689   /**
690    * The renderer service.
691    *
692    * @var \Drupal\Core\Render\RendererInterface
693    */
694   protected $renderer;
695
696   /**
697    * The migration plugin manager.
698    *
699    * @var \Drupal\migrate\Plugin\MigrationPluginManagerInterface
700    */
701   protected $pluginManager;
702
703   /**
704    * Constructs the MigrateUpgradeForm.
705    *
706    * @param \Drupal\Core\State\StateInterface $state
707    *   The state service.
708    * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
709    *   The date formatter service.
710    * @param \Drupal\Core\Render\RendererInterface $renderer
711    *   The renderer service.
712    * @param \Drupal\migrate\Plugin\MigrationPluginManagerInterface $plugin_manager
713    *   The migration plugin manager.
714    */
715   public function __construct(StateInterface $state, DateFormatterInterface $date_formatter, RendererInterface $renderer, MigrationPluginManagerInterface $plugin_manager) {
716     $this->state = $state;
717     $this->dateFormatter = $date_formatter;
718     $this->renderer = $renderer;
719     $this->pluginManager = $plugin_manager;
720   }
721
722   /**
723    * {@inheritdoc}
724    */
725   public static function create(ContainerInterface $container) {
726     return new static(
727       $container->get('state'),
728       $container->get('date.formatter'),
729       $container->get('renderer'),
730       $container->get('plugin.manager.migration')
731     );
732   }
733
734   /**
735    * {@inheritdoc}
736    */
737   public function getFormId() {
738     return 'migrate_drupal_ui_form';
739   }
740
741   /**
742    * {@inheritdoc}
743    */
744   public function buildForm(array $form, FormStateInterface $form_state) {
745     $step = $form_state->get('step') ?: 'overview';
746     switch ($step) {
747       case 'overview':
748         return $this->buildOverviewForm($form, $form_state);
749
750       case 'credentials':
751         return $this->buildCredentialForm($form, $form_state);
752
753       case 'confirm':
754         return $this->buildConfirmForm($form, $form_state);
755
756       default:
757         drupal_set_message($this->t('Unrecognized form step @step', ['@step' => $step]), 'error');
758         return [];
759     }
760   }
761
762   /**
763    * {@inheritdoc}
764    */
765   public function submitForm(array &$form, FormStateInterface $form_state) {
766     // This method is intentionally empty, see the specific submit methods for
767     // each form step.
768   }
769
770   /**
771    * Builds the form presenting an overview of the migration process.
772    *
773    * @param array $form
774    *   An associative array containing the structure of the form.
775    * @param \Drupal\Core\Form\FormStateInterface $form_state
776    *   The current state of the form.
777    *
778    * @return array
779    *   The form structure.
780    */
781   public function buildOverviewForm(array $form, FormStateInterface $form_state) {
782     $form['#title'] = $this->t('Upgrade');
783
784     if ($date_performed = $this->state->get('migrate_drupal_ui.performed')) {
785       // @todo Add back support for rollbacks and incremental migrations.
786       //   https://www.drupal.org/node/2687843
787       //   https://www.drupal.org/node/2687849
788       $form['upgrade_option_item'] = [
789         '#type' => 'item',
790         '#prefix' => $this->t('An upgrade has already been performed on this site. To perform a new migration, create a clean and empty new install of Drupal 8. Rollbacks and incremental migrations are not yet supported through the user interface. For more information, see the <a href=":url">upgrading handbook</a>.', [':url' => 'https://www.drupal.org/upgrade/migrate']),
791         '#description' => $this->t('Last upgrade: @date', ['@date' => $this->dateFormatter->format($date_performed)]),
792       ];
793       return $form;
794     }
795     else {
796       $form['info_header'] = [
797         '#markup' => '<p>' . $this->t('Upgrade a site by importing it into a clean and empty new install of Drupal 8. You will lose any existing configuration once you import your site into it. See the <a href=":url">online documentation for Drupal site upgrades</a> for more detailed information.', [
798           ':url' => 'https://www.drupal.org/upgrade/migrate',
799         ]),
800       ];
801
802       $info[] = $this->t('<strong>Back up the database for this site</strong>. Upgrade will change the database for this site.');
803       $info[] = $this->t('Make sure that the host this site is on has access to the database for your previous site.');
804       $info[] = $this->t('If your previous site has private files to be migrated, a copy of your files directory must be accessible on the host this site is on.');
805       $info[] = $this->t('In general, enable all modules on this site that are enabled on the previous site. For example, if you have used the book module on the previous site then you must enable the book module on this site for that data to be available on this site.');
806       $info[] = $this->t('Do not add any information on this site (including but not limited to user accounts, taxonomy terms, and node content) before upgrading. Any pre-existing information on the site risks being overwritten by the upgrade process. See <a href=":url">the upgrade preparation guide</a> for more information.', [
807         ':url' => 'https://www.drupal.org/docs/8/upgrade/preparing-an-upgrade#dont_create_content',
808       ]);
809       $info[] = $this->t('Put this site into <a href=":url">maintenance mode</a>.', [
810         ':url' => Url::fromRoute('system.site_maintenance_mode')->toString(TRUE)->getGeneratedUrl(),
811       ]);
812
813       $form['info'] = [
814         '#theme' => 'item_list',
815         '#list_type' => 'ol',
816         '#items' => $info,
817       ];
818
819       $form['info_footer'] = [
820         '#markup' => '<p>' . $this->t('This upgrade can take a long time. It is better to import a local copy of your site instead of directly importing from your live site.'),
821       ];
822
823       $validate = [];
824     }
825
826     $form['actions'] = ['#type' => 'actions'];
827     $form['actions']['save'] = [
828       '#type' => 'submit',
829       '#value' => $this->t('Continue'),
830       '#button_type' => 'primary',
831       '#validate' => $validate,
832       '#submit' => ['::submitOverviewForm'],
833     ];
834     return $form;
835   }
836
837   /**
838    * Form submission handler for the overview form.
839    *
840    * @param array $form
841    *   An associative array containing the structure of the form.
842    * @param \Drupal\Core\Form\FormStateInterface $form_state
843    *   The current state of the form.
844    */
845   public function submitOverviewForm(array &$form, FormStateInterface $form_state) {
846     $form_state->set('step', 'credentials');
847     $form_state->setRebuild();
848   }
849
850   /**
851    * Builds the database credential form and adds file location information.
852    *
853    * This is largely borrowed from \Drupal\Core\Installer\Form\SiteSettingsForm.
854    *
855    * @param array $form
856    *   An associative array containing the structure of the form.
857    * @param \Drupal\Core\Form\FormStateInterface $form_state
858    *   The current state of the form.
859    *
860    * @return array
861    *   The form structure.
862    *
863    * @todo Private files directory not yet implemented, depends on
864    *   https://www.drupal.org/node/2547125.
865    */
866   public function buildCredentialForm(array $form, FormStateInterface $form_state) {
867     $form['#title'] = $this->t('Drupal Upgrade');
868
869     $drivers = $this->getDatabaseTypes();
870     $drivers_keys = array_keys($drivers);
871     // @todo https://www.drupal.org/node/2678510 Because this is a multi-step
872     //   form, the form is not rebuilt during submission. Ideally we would get
873     //   the chosen driver from form input, if available, in order to use
874     //   #limit_validation_errors in the same way
875     //   \Drupal\Core\Installer\Form\SiteSettingsForm does.
876     $default_driver = current($drivers_keys);
877
878     $default_options = [];
879
880     $form['database'] = [
881       '#type' => 'details',
882       '#title' => $this->t('Source database'),
883       '#description' => $this->t('Provide credentials for the database of the Drupal site you want to upgrade.'),
884       '#open' => TRUE,
885     ];
886
887     $form['database']['driver'] = [
888       '#type' => 'radios',
889       '#title' => $this->t('Database type'),
890       '#required' => TRUE,
891       '#default_value' => $default_driver,
892     ];
893     if (count($drivers) == 1) {
894       $form['database']['driver']['#disabled'] = TRUE;
895     }
896
897     // Add driver-specific configuration options.
898     foreach ($drivers as $key => $driver) {
899       $form['database']['driver']['#options'][$key] = $driver->name();
900
901       $form['database']['settings'][$key] = $driver->getFormOptions($default_options);
902       // @todo https://www.drupal.org/node/2678510 Using
903       //   #limit_validation_errors in the submit does not work so it is not
904       //   possible to require the database and username for mysql and pgsql.
905       //   This is because this is a multi-step form.
906       $form['database']['settings'][$key]['database']['#required'] = FALSE;
907       $form['database']['settings'][$key]['username']['#required'] = FALSE;
908       $form['database']['settings'][$key]['#prefix'] = '<h2 class="js-hide">' . $this->t('@driver_name settings', ['@driver_name' => $driver->name()]) . '</h2>';
909       $form['database']['settings'][$key]['#type'] = 'container';
910       $form['database']['settings'][$key]['#tree'] = TRUE;
911       $form['database']['settings'][$key]['advanced_options']['#parents'] = [$key];
912       $form['database']['settings'][$key]['#states'] = [
913         'visible' => [
914           ':input[name=driver]' => ['value' => $key],
915         ],
916       ];
917
918       // Move the host fields out of advanced settings.
919       if (isset($form['database']['settings'][$key]['advanced_options']['host'])) {
920         $form['database']['settings'][$key]['host'] = $form['database']['settings'][$key]['advanced_options']['host'];
921         $form['database']['settings'][$key]['host']['#title'] = 'Database host';
922         $form['database']['settings'][$key]['host']['#weight'] = -1;
923         unset($form['database']['settings'][$key]['database']['#default_value']);
924         unset($form['database']['settings'][$key]['advanced_options']['host']);
925       }
926     }
927
928     $form['source'] = [
929       '#type' => 'details',
930       '#title' => $this->t('Source files'),
931       '#open' => TRUE,
932     ];
933     $form['source']['source_base_path'] = [
934       '#type' => 'textfield',
935       '#title' => $this->t('Files directory'),
936       '#description' => $this->t('To import files from your current Drupal site, enter a local file directory containing your site (e.g. /var/www/docroot), or your site address (for example http://example.com).'),
937     ];
938
939     $form['actions'] = ['#type' => 'actions'];
940     $form['actions']['save'] = [
941       '#type' => 'submit',
942       '#value' => $this->t('Review upgrade'),
943       '#button_type' => 'primary',
944       '#validate' => ['::validateCredentialForm'],
945       '#submit' => ['::submitCredentialForm'],
946     ];
947     return $form;
948   }
949
950   /**
951    * Validation handler for the credentials form.
952    *
953    * @param array $form
954    *   An associative array containing the structure of the form.
955    * @param \Drupal\Core\Form\FormStateInterface $form_state
956    *   The current state of the form.
957    */
958   public function validateCredentialForm(array &$form, FormStateInterface $form_state) {
959
960     // Retrieve the database driver from the form, use reflection to get the
961     // namespace, and then construct a valid database array the same as in
962     // settings.php.
963     $driver = $form_state->getValue('driver');
964     $drivers = $this->getDatabaseTypes();
965     $reflection = new \ReflectionClass($drivers[$driver]);
966     $install_namespace = $reflection->getNamespaceName();
967
968     $database = $form_state->getValue($driver);
969     // Cut the trailing \Install from namespace.
970     $database['namespace'] = substr($install_namespace, 0, strrpos($install_namespace, '\\'));
971     $database['driver'] = $driver;
972
973     // Validate the driver settings and just end here if we have any issues.
974     if ($errors = $drivers[$driver]->validateDatabaseSettings($database)) {
975       foreach ($errors as $name => $message) {
976         $form_state->setErrorByName($name, $message);
977       }
978       return;
979     }
980
981     try {
982       $connection = $this->getConnection($database);
983       $version = $this->getLegacyDrupalVersion($connection);
984       if (!$version) {
985         $form_state->setErrorByName($database['driver'] . '][0', $this->t('Source database does not contain a recognizable Drupal version.'));
986       }
987       else {
988         $this->createDatabaseStateSettings($database, $version);
989         $migrations = $this->getMigrations('migrate_drupal_' . $version, $version);
990
991         // Get the system data from source database.
992         $system_data = $this->getSystemData($connection);
993
994         // Convert the migration object into array
995         // so that it can be stored in form storage.
996         $migration_array = [];
997         foreach ($migrations as $migration) {
998           $migration_array[$migration->id()] = $migration->label();
999         }
1000
1001         // Store the retrieved migration IDs in form storage.
1002         $form_state->set('migrations', $migration_array);
1003         $form_state->set('source_base_path', $form_state->getValue('source_base_path'));
1004
1005         // Store the retrived system data in form storage.
1006         $form_state->set('system_data', $system_data);
1007       }
1008     }
1009     catch (\Exception $e) {
1010       $error_message = [
1011         '#title' => $this->t('Resolve the issue below to continue the upgrade.'),
1012         '#theme' => 'item_list',
1013         '#items' => [$e->getMessage()],
1014       ];
1015       $form_state->setErrorByName($database['driver'] . '][0', $this->renderer->renderPlain($error_message));
1016     }
1017   }
1018
1019   /**
1020    * Submission handler for the credentials form.
1021    *
1022    * @param array $form
1023    *   An associative array containing the structure of the form.
1024    * @param \Drupal\Core\Form\FormStateInterface $form_state
1025    *   The current state of the form.
1026    */
1027   public function submitCredentialForm(array &$form, FormStateInterface $form_state) {
1028     // Indicate the next step is confirmation.
1029     $form_state->set('step', 'confirm');
1030     $form_state->setRebuild();
1031   }
1032
1033   /**
1034    * Confirmation form for missing migrations, etc.
1035    *
1036    * @param array $form
1037    *   An associative array containing the structure of the form.
1038    * @param \Drupal\Core\Form\FormStateInterface $form_state
1039    *   The current state of the form.
1040    *
1041    * @return array
1042    *   The form structure.
1043    */
1044   public function buildConfirmForm(array $form, FormStateInterface $form_state) {
1045     $form = parent::buildForm($form, $form_state);
1046     $form['actions']['submit']['#submit'] = ['::submitConfirmForm'];
1047
1048     $form['actions']['submit']['#value'] = $this->t('Perform upgrade');
1049
1050     $table_data = [];
1051     $system_data = [];
1052     foreach ($form_state->get('migrations') as $migration_id => $migration_label) {
1053       // Fetch the system data at the first opportunity.
1054       if (empty($system_data)) {
1055         $system_data = $form_state->get('system_data');
1056       }
1057
1058       // Handle derivatives.
1059       list($migration_id,) = explode(':', $migration_id, 2);
1060       $source_module = $this->moduleUpgradePaths[$migration_id]['source_module'];
1061       $destination_module = $this->moduleUpgradePaths[$migration_id]['destination_module'];
1062       $table_data[$source_module][$destination_module][$migration_id] = $migration_label;
1063     }
1064     // Sort the table by source module names and within that destination
1065     // module names.
1066     ksort($table_data);
1067     foreach ($table_data as $source_module => $destination_module_info) {
1068       ksort($table_data[$source_module]);
1069     }
1070     $unmigrated_source_modules = array_diff_key($system_data['module'], $table_data);
1071
1072     // Missing migrations.
1073     $form['missing_module_list_title'] = [
1074       '#type' => 'item',
1075       '#title' => $this->t('Missing upgrade paths'),
1076       '#description' => $this->t('The following items will not be upgraded. For more information see <a href=":migrate">Upgrading from Drupal 6 or 7 to Drupal 8</a>.', [':migrate' => 'https://www.drupal.org/upgrade/migrate']),
1077     ];
1078     $form['missing_module_list'] = [
1079       '#type' => 'table',
1080       '#header' => [
1081         $this->t('Source'),
1082         $this->t('Destination'),
1083       ],
1084     ];
1085     $missing_count = 0;
1086     ksort($unmigrated_source_modules);
1087     foreach ($unmigrated_source_modules as $source_module => $module_data) {
1088       if ($module_data['status']) {
1089         $missing_count++;
1090         $form['missing_module_list'][$source_module] = [
1091           'source_module' => ['#plain_text' => $source_module],
1092           'destination_module' => ['#plain_text' => 'Missing'],
1093         ];
1094       }
1095     }
1096     // Available migrations.
1097     $form['available_module_list'] = [
1098       '#tree' => TRUE,
1099       '#type' => 'details',
1100       '#title' => $this->t('Available upgrade paths'),
1101     ];
1102
1103     $form['available_module_list']['module_list'] = [
1104       '#type' => 'table',
1105       '#header' => [
1106         $this->t('Source'),
1107         $this->t('Destination'),
1108       ],
1109     ];
1110
1111     $available_count = 0;
1112     foreach ($table_data as $source_module => $destination_module_info) {
1113       $available_count++;
1114       $destination_details = [];
1115       foreach ($destination_module_info as $destination_module => $migration_ids) {
1116         $destination_details[$destination_module] = [
1117           '#type' => 'item',
1118           '#plain_text' => $destination_module,
1119         ];
1120       }
1121       $form['available_module_list']['module_list'][$source_module] = [
1122         'source_module' => ['#plain_text' => $source_module],
1123         'destination_module' => $destination_details,
1124       ];
1125     }
1126     $form['counts'] = [
1127       '#title' => 'Upgrade analysis report',
1128       '#theme' => 'item_list',
1129       '#items' => [
1130         $this->formatPlural($available_count, '@count available upgrade path', '@count available upgrade paths'),
1131         $this->formatPlural($missing_count, '@count missing upgrade path', '@count missing upgrade paths'),
1132       ],
1133       '#weight' => -15,
1134     ];
1135
1136     return $form;
1137   }
1138
1139   /**
1140    * Submission handler for the confirmation form.
1141    *
1142    * @param array $form
1143    *   An associative array containing the structure of the form.
1144    * @param \Drupal\Core\Form\FormStateInterface $form_state
1145    *   The current state of the form.
1146    */
1147   public function submitConfirmForm(array &$form, FormStateInterface $form_state) {
1148     $storage = $form_state->getStorage();
1149
1150     $migrations = $storage['migrations'];
1151     $config['source_base_path'] = $storage['source_base_path'];
1152     $batch = [
1153       'title' => $this->t('Running upgrade'),
1154       'progress_message' => '',
1155       'operations' => [
1156         [
1157           [MigrateUpgradeImportBatch::class, 'run'],
1158           [array_keys($migrations), $config],
1159         ],
1160       ],
1161       'finished' => [
1162         MigrateUpgradeImportBatch::class, 'finished',
1163       ],
1164     ];
1165     batch_set($batch);
1166     $form_state->setRedirect('<front>');
1167     $this->state->set('migrate_drupal_ui.performed', REQUEST_TIME);
1168   }
1169
1170   /**
1171    * Returns all supported database driver installer objects.
1172    *
1173    * @return \Drupal\Core\Database\Install\Tasks[]
1174    *   An array of available database driver installer objects.
1175    */
1176   protected function getDatabaseTypes() {
1177     // Make sure the install API is available.
1178     include_once DRUPAL_ROOT . '/core/includes/install.inc';
1179     return drupal_get_database_types();
1180   }
1181
1182   /**
1183    * {@inheritdoc}
1184    */
1185   public function getQuestion() {
1186     return $this->t('Are you sure?');
1187   }
1188
1189   /**
1190    * {@inheritdoc}
1191    */
1192   public function getCancelUrl() {
1193     return new Url('migrate_drupal_ui.upgrade');
1194   }
1195
1196   /**
1197    * {@inheritdoc}
1198    */
1199   public function getDescription() {
1200     // The description is added by the buildConfirmForm() method.
1201     // @see \Drupal\migrate_drupal_ui\Form\MigrateUpgradeForm::buildConfirmForm()
1202     return;
1203   }
1204
1205   /**
1206    * {@inheritdoc}
1207    */
1208   public function getConfirmText() {
1209     return $this->t('Perform upgrade');
1210   }
1211
1212 }