19dd60b3571beb1cb21ae703a7469e4387dd3387
[yaffs-website] / web / core / modules / migrate_drupal_ui / src / Form / ReviewForm.php
1 <?php
2
3 namespace Drupal\migrate_drupal_ui\Form;
4
5 use Drupal\Core\Form\FormStateInterface;
6 use Drupal\Core\State\StateInterface;
7 use Drupal\Core\TempStore\PrivateTempStoreFactory;
8 use Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface;
9 use Drupal\migrate\Plugin\MigrationPluginManagerInterface;
10 use Drupal\migrate_drupal_ui\Batch\MigrateUpgradeImportBatch;
11 use Symfony\Component\DependencyInjection\ContainerInterface;
12
13 /**
14  * Migrate Upgrade review form.
15  *
16  * This confirmation form uses the source_module and destination_module
17  * properties on the source, destination and field plugins as well as the
18  * system data from the source to determine if there is a migration path for
19  * each module in the source.
20  *
21  * @internal
22  */
23 class ReviewForm extends MigrateUpgradeFormBase {
24
25   /**
26    * The state service.
27    *
28    * @var \Drupal\Core\State\StateInterface
29    */
30   protected $state;
31
32   /**
33    * The migration plugin manager service.
34    *
35    * @var \Drupal\migrate\Plugin\MigrationPluginManagerInterface
36    */
37   protected $pluginManager;
38
39   /**
40    * The field plugin manager service.
41    *
42    * @var \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface
43    */
44   protected $fieldPluginManager;
45
46   /**
47    * The migrations.
48    *
49    * @var \Drupal\migrate\Plugin\MigrationInterface[]
50    */
51   protected $migrations;
52
53   /**
54    * List of extensions that do not need an upgrade path.
55    *
56    * This property is an array where the keys are the major Drupal core version
57    * from which we are upgrading, and the values are arrays of extension names
58    * that do not need an upgrade path.
59    *
60    * @var array[]
61    */
62   protected $noUpgradePaths = [
63     '6' => [
64       'blog',
65       'blogapi',
66       'calendarsignup',
67       'color',
68       'content_copy',
69       'content_multigroup',
70       'content_permissions',
71       'date_api',
72       'date_locale',
73       'date_php4',
74       'date_popup',
75       'date_repeat',
76       'date_timezone',
77       'date_tools',
78       'datepicker',
79       'ddblock',
80       'event',
81       'fieldgroup',
82       'filefield_meta',
83       'help',
84       'i18n',
85       'i18nstrings',
86       'imageapi',
87       'imageapi_gd',
88       'imageapi_imagemagick',
89       'imagecache_ui',
90       'jquery_ui',
91       'nodeaccess',
92       'number',
93       'openid',
94       'php',
95       'ping',
96       'poll',
97       'throttle',
98       'tracker',
99       'translation',
100       'trigger',
101       'variable',
102       'variable_admin',
103       'views_export',
104       'views_ui',
105     ],
106     '7' => [
107       'blog',
108       'bulk_export',
109       'contextual',
110       'ctools',
111       'ctools_access_ruleset',
112       'ctools_ajax_sample',
113       'ctools_custom_content',
114       'dashboard',
115       'date_all_day',
116       'date_api',
117       'date_context',
118       'date_migrate',
119       'date_popup',
120       'date_repeat',
121       'date_repeat_field',
122       'date_tools',
123       'date_views',
124       'entity',
125       'entity_feature',
126       'entity_token',
127       'entityreference',
128       'field_ui',
129       'help',
130       'openid',
131       'overlay',
132       'page_manager',
133       'php',
134       'poll',
135       'search_embedded_form',
136       'search_extra_type',
137       'search_node_tags',
138       'simpletest',
139       'stylizer',
140       'term_depth',
141       'toolbar',
142       'translation',
143       'trigger',
144       'views_content',
145       'views_ui',
146     ],
147   ];
148
149   /**
150    * ReviewForm constructor.
151    *
152    * @param \Drupal\Core\State\StateInterface $state
153    *   The state service.
154    * @param \Drupal\migrate\Plugin\MigrationPluginManagerInterface $migration_plugin_manager
155    *   The migration plugin manager service.
156    * @param \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface $field_plugin_manager
157    *   The field plugin manager service.
158    * @param \Drupal\Core\TempStore\PrivateTempStoreFactory $tempstore_private
159    *   The private tempstore factory.
160    */
161   public function __construct(StateInterface $state, MigrationPluginManagerInterface $migration_plugin_manager, MigrateFieldPluginManagerInterface $field_plugin_manager, PrivateTempStoreFactory $tempstore_private) {
162     parent::__construct($tempstore_private);
163     $this->state = $state;
164     $this->pluginManager = $migration_plugin_manager;
165     $this->fieldPluginManager = $field_plugin_manager;
166   }
167
168   /**
169    * {@inheritdoc}
170    */
171   public static function create(ContainerInterface $container) {
172     return new static(
173       $container->get('state'),
174       $container->get('plugin.manager.migration'),
175       $container->get('plugin.manager.migrate.field'),
176       $container->get('tempstore.private')
177     );
178   }
179
180   /**
181    * {@inheritdoc}
182    */
183   public function getFormId() {
184     return 'migrate_drupal_ui_review_form';
185   }
186
187   /**
188    * {@inheritdoc}
189    */
190   public function buildForm(array $form, FormStateInterface $form_state) {
191     // Get all the data needed for this form.
192     $version = $this->store->get('version');
193     $this->migrations = $this->store->get('migrations');
194     // Fetch the system data at the first opportunity.
195     $system_data = $this->store->get('system_data');
196
197     // If data is missing or this is the wrong step, start over.
198     if (!$version || !$this->migrations || !$system_data ||
199       ($this->store->get('step') != 'review')) {
200       return $this->restartUpgradeForm();
201     }
202
203     $form = parent::buildForm($form, $form_state);
204     $form['#title'] = $this->t('What will be upgraded?');
205
206     // Get the source_module and destination_module for each migration.
207     $migrations = $this->pluginManager->createInstances(array_keys($this->store->get('migrations')));
208     $table_data = [];
209     foreach ($migrations as $migration) {
210       $migration_id = $migration->getPluginId();
211       $source_module = $migration->getSourcePlugin()->getSourceModule();
212       if (!$source_module) {
213         $this->messenger()->addError($this->t('Source module not found for @migration_id.', ['@migration_id' => $migration_id]));
214       }
215       $destination_module = $migration->getDestinationPlugin()->getDestinationModule();
216       if (!$destination_module) {
217         $this->messenger()->addError($this->t('Destination module not found for @migration_id.', ['@migration_id' => $migration_id]));
218       }
219
220       if ($source_module && $destination_module) {
221         $table_data[$source_module][$destination_module][$migration_id] = $migration->label();
222       }
223     }
224
225     // Get the source_module and destination_module from the field plugins.
226     $definitions = $this->fieldPluginManager->getDefinitions();
227     foreach ($definitions as $definition) {
228       // This is not strict so that we find field plugins with an annotation
229       // where the Drupal core version is an integer and when it is a string.
230       if (in_array($version, $definition['core'])) {
231         $source_module = $definition['source_module'];
232         $destination_module = $definition['destination_module'];
233         $table_data[$source_module][$destination_module][$definition['id']] = $definition['id'];
234       }
235     }
236
237     // Add source_module and destination_module for modules that do not need an
238     // upgrade path and are enabled on the source site.
239     foreach ($this->noUpgradePaths[$version] as $extension) {
240       if ($system_data['module'][$extension]['status']) {
241         $table_data[$extension]['core'][$extension] = $extension;
242       }
243     }
244
245     // Sort the table by source module names and within that destination
246     // module names.
247     ksort($table_data);
248     foreach ($table_data as $source_module => $destination_module_info) {
249       ksort($table_data[$source_module]);
250     }
251
252     // Remove core profiles from the system data.
253     foreach (['standard', 'minimal'] as $profile) {
254       unset($system_data['module'][$profile]);
255     }
256
257     $unmigrated_source_modules = array_diff_key($system_data['module'], $table_data);
258
259     // Missing migrations.
260     $missing_module_list = [
261       '#type' => 'details',
262       '#open' => TRUE,
263       '#title' => [
264         '#type' => 'html_tag',
265         '#tag' => 'span',
266         '#value' => $this->t('Modules that will not be upgraded'),
267         '#attributes' => ['id' => ['error']],
268       ],
269       '#description' => $this->t('There are no modules installed on your new site to replace these modules. If you proceed with the upgrade now, configuration and/or content needed by these modules will not be available on your new site. For more information, see <a href=":review">Review the pre-upgrade analysis</a> in the <a href=":migrate">Upgrading to Drupal 8</a> handbook.', [':review' => 'https://www.drupal.org/docs/8/upgrade/upgrade-using-web-browser#pre-upgrade-analysis', ':migrate' => 'https://www.drupal.org/docs/8/upgrade']),
270       '#weight' => 2,
271     ];
272     $missing_module_list['module_list'] = [
273       '#type' => 'table',
274       '#header' => [
275         $this->t('Drupal @version', ['@version' => $version]),
276         $this->t('Drupal 8'),
277       ],
278     ];
279     $missing_count = 0;
280     ksort($unmigrated_source_modules);
281     foreach ($unmigrated_source_modules as $source_module => $module_data) {
282       if ($module_data['status']) {
283         $missing_count++;
284         $missing_module_list['module_list'][$source_module] = [
285           'source_module' => [
286             '#type' => 'html_tag',
287             '#tag' => 'span',
288             '#value' => $source_module,
289             '#attributes' => [
290               'class' => [
291                 'upgrade-analysis-report__status-icon',
292                 'upgrade-analysis-report__status-icon--error',
293               ],
294             ],
295           ],
296           'destination_module' => ['#plain_text' => 'Not upgraded'],
297         ];
298       }
299     }
300
301     // Available migrations.
302     $available_module_list = [
303       '#type' => 'details',
304       '#title' => [
305         '#type' => 'html_tag',
306         '#tag' => 'span',
307         '#value' => $this->t('Modules that will be upgraded'),
308         '#attributes' => ['id' => ['checked']],
309       ],
310       '#weight' => 3,
311     ];
312
313     $available_module_list['module_list'] = [
314       '#type' => 'table',
315       '#header' => [
316         $this->t('Drupal @version', ['@version' => $version]),
317         $this->t('Drupal 8'),
318       ],
319     ];
320
321     $available_count = 0;
322     foreach ($table_data as $source_module => $destination_module_info) {
323       $available_count++;
324       $destination_details = [];
325       foreach ($destination_module_info as $destination_module => $migration_ids) {
326         $destination_details[$destination_module] = [
327           '#type' => 'item',
328           '#plain_text' => $destination_module,
329         ];
330       }
331       $available_module_list['module_list'][$source_module] = [
332         'source_module' => [
333           '#type' => 'html_tag',
334           '#tag' => 'span',
335           '#value' => $source_module,
336           '#attributes' => [
337             'class' => [
338               'upgrade-analysis-report__status-icon',
339               'upgrade-analysis-report__status-icon--checked',
340             ],
341           ],
342         ],
343         'destination_module' => $destination_details,
344       ];
345     }
346
347     $counters = [];
348     $general_info = [];
349
350     if ($missing_count) {
351       $counters[] = [
352         '#theme' => 'status_report_counter',
353         '#amount' => $missing_count,
354         '#text' => $this->formatPlural($missing_count, 'Module will not be upgraded', 'Modules will not be upgraded'),
355         '#severity' => 'error',
356         '#weight' => 0,
357       ];
358       $general_info[] = $missing_module_list;
359     }
360     if ($available_count) {
361       $counters[] = [
362         '#theme' => 'status_report_counter',
363         '#amount' => $available_count,
364         '#text' => $this->formatPlural($available_count, 'Module will be upgraded', 'Modules will be upgraded'),
365         '#severity' => 'checked',
366         '#weight' => 1,
367       ];
368       $general_info[] = $available_module_list;
369     }
370
371     $form['status_report_page'] = [
372       '#theme' => 'status_report_page',
373       '#counters' => $counters,
374       '#general_info' => $general_info,
375     ];
376
377     $form['#attached']['library'][] = 'migrate_drupal_ui/base';
378
379     return $form;
380   }
381
382   /**
383    * {@inheritdoc}
384    */
385   public function submitForm(array &$form, FormStateInterface $form_state) {
386     $config['source_base_path'] = $this->store->get('source_base_path');
387     $batch = [
388       'title' => $this->t('Running upgrade'),
389       'progress_message' => '',
390       'operations' => [
391         [
392           [MigrateUpgradeImportBatch::class, 'run'],
393           [array_keys($this->migrations), $config],
394         ],
395       ],
396       'finished' => [
397         MigrateUpgradeImportBatch::class, 'finished',
398       ],
399     ];
400     batch_set($batch);
401     $form_state->setRedirect('<front>');
402     $this->store->set('step', 'overview');
403     $this->state->set('migrate_drupal_ui.performed', REQUEST_TIME);
404   }
405
406   /**
407    * {@inheritdoc}
408    */
409   public function getConfirmText() {
410     return $this->t('Perform upgrade');
411   }
412
413 }