function DbUpdateController::selection

Same name in other branches
  1. 9 core/modules/system/src/Controller/DbUpdateController.php \Drupal\system\Controller\DbUpdateController::selection()
  2. 10 core/modules/system/src/Controller/DbUpdateController.php \Drupal\system\Controller\DbUpdateController::selection()
  3. 11.x core/modules/system/src/Controller/DbUpdateController.php \Drupal\system\Controller\DbUpdateController::selection()

Renders a list of available database updates.

Parameters

\Symfony\Component\HttpFoundation\Request $request: The current request.

Return value

array A render array.

1 call to DbUpdateController::selection()
DbUpdateController::handle in core/modules/system/src/Controller/DbUpdateController.php
Returns a database update page.

File

core/modules/system/src/Controller/DbUpdateController.php, line 254

Class

DbUpdateController
Controller routines for database update routes.

Namespace

Drupal\system\Controller

Code

protected function selection(Request $request) {
    // Make sure there is no stale theme registry.
    $this->cache
        ->deleteAll();
    $count = 0;
    $incompatible_count = 0;
    $build['start'] = [
        '#tree' => TRUE,
        '#type' => 'details',
    ];
    // Ensure system.module's updates appear first.
    $build['start']['system'] = [];
    $starting_updates = [];
    $incompatible_updates_exist = FALSE;
    $updates_per_module = [];
    foreach ([
        'update',
        'post_update',
    ] as $update_type) {
        switch ($update_type) {
            case 'update':
                $updates = update_get_update_list();
                break;
            case 'post_update':
                $updates = $this->postUpdateRegistry
                    ->getPendingUpdateInformation();
                break;
        }
        foreach ($updates as $module => $update) {
            if (!isset($update['start'])) {
                $build['start'][$module] = [
                    '#type' => 'item',
                    '#title' => $module . ' module',
                    '#markup' => $update['warning'],
                    '#prefix' => '<div class="messages messages--warning">',
                    '#suffix' => '</div>',
                ];
                $incompatible_updates_exist = TRUE;
                continue;
            }
            if (!empty($update['pending'])) {
                $updates_per_module += [
                    $module => [],
                ];
                $updates_per_module[$module] = array_merge($updates_per_module[$module], $update['pending']);
                $build['start'][$module] = [
                    '#type' => 'hidden',
                    '#value' => $update['start'],
                ];
                // Store the previous items in order to merge normal updates and
                // post_update functions together.
                $build['start'][$module] = [
                    '#theme' => 'item_list',
                    '#items' => $updates_per_module[$module],
                    '#title' => $module . ' module',
                ];
                if ($update_type === 'update') {
                    $starting_updates[$module] = $update['start'];
                }
            }
            if (isset($update['pending'])) {
                $count = $count + count($update['pending']);
            }
        }
    }
    // Find and label any incompatible updates.
    foreach (update_resolve_dependencies($starting_updates) as $data) {
        if (!$data['allowed']) {
            $incompatible_updates_exist = TRUE;
            $incompatible_count++;
            $module_update_key = $data['module'] . '_updates';
            if (isset($build['start'][$module_update_key]['#items'][$data['number']])) {
                if ($data['missing_dependencies']) {
                    $text = $this->t('This update will been skipped due to the following missing dependencies:') . '<em>' . implode(', ', $data['missing_dependencies']) . '</em>';
                }
                else {
                    $text = $this->t("This update will be skipped due to an error in the module's code.");
                }
                $build['start'][$module_update_key]['#items'][$data['number']] .= '<div class="warning">' . $text . '</div>';
            }
            // Move the module containing this update to the top of the list.
            $build['start'] = [
                $module_update_key => $build['start'][$module_update_key],
            ] + $build['start'];
        }
    }
    // Warn the user if any updates were incompatible.
    if ($incompatible_updates_exist) {
        $this->messenger()
            ->addWarning($this->t('Some of the pending updates cannot be applied because their dependencies were not met.'));
    }
    if (empty($count)) {
        $this->messenger()
            ->addStatus($this->t('No pending updates.'));
        unset($build);
        $build['links'] = [
            '#theme' => 'links',
            '#links' => $this->helpfulLinks($request),
        ];
        // No updates to run, so caches won't get flushed later.  Clear them now.
        drupal_flush_all_caches();
    }
    else {
        $build['help'] = [
            '#markup' => '<p>' . $this->t('The version of Drupal you are updating from has been automatically detected.') . '</p>',
            '#weight' => -5,
        ];
        if ($incompatible_count) {
            $build['start']['#title'] = $this->formatPlural($count, '1 pending update (@number_applied to be applied, @number_incompatible skipped)', '@count pending updates (@number_applied to be applied, @number_incompatible skipped)', [
                '@number_applied' => $count - $incompatible_count,
                '@number_incompatible' => $incompatible_count,
            ]);
        }
        else {
            $build['start']['#title'] = $this->formatPlural($count, '1 pending update', '@count pending updates');
        }
        // @todo Simplify with https://www.drupal.org/node/2548095
        $base_url = str_replace('/update.php', '', $request->getBaseUrl());
        $url = (new Url('system.db_update', [
            'op' => 'run',
        ]))->setOption('base_url', $base_url);
        $build['link'] = [
            '#type' => 'link',
            '#title' => $this->t('Apply pending updates'),
            '#attributes' => [
                'class' => [
                    'button',
                    'button--primary',
                ],
            ],
            '#weight' => 5,
            '#url' => $url,
            '#access' => $url->access($this->currentUser()),
        ];
    }
    return $build;
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.