5 * Implementation of 'drupal' update_status engine for Drupal 8.
8 namespace Drush\UpdateService;
10 class StatusInfoDrupal8 implements StatusInfoInterface {
15 public function __construct($type, $engine, $config) {
16 $this->engine_type = $type;
17 $this->engine = $engine;
18 $this->engine_config = $config;
24 function lastCheck() {
25 $last_check = \Drupal::state()->get('update.last_check') ?: 0;
37 * Perform adjustments before running get status.
39 * - Enforce check-disabled option on update module.
41 function beforeGetStatus(&$projects, $check_disabled) {
42 // If check-disabled option was provided, alter Drupal settings temporarily.
43 // There's no other way to hook into this.
44 if (!is_null($check_disabled)) {
45 $config = \Drupal::config('update.settings');
46 $this->update_check_disabled = $config->get('check.disabled_extensions');
47 $config->set('check.disabled_extensions', (bool)$check_disabled);
52 * Get update information for all installed projects.
55 * Array of update status information.
57 function getStatus($projects, $check_disabled) {
58 $this->beforeGetStatus($projects, $check_disabled);
59 $available = $this->getAvailableReleases();
60 $update_info = $this->calculateUpdateStatus($available, $projects);
61 $this->afterGetStatus($update_info, $projects, $check_disabled);
66 * Perform adjustments after running get status.
68 * - Restore check-disabled setting in update module.
69 * - Adjust project type for disabled projects.
71 function afterGetStatus(&$update_info, $projects, $check_disabled) {
72 // Restore Drupal settings.
73 if (!is_null($check_disabled)) {
74 \Drupal::config('update.settings')->set('check.disabled_extensions', $this->update_check_disabled);
75 unset($this->update_check_disabled);
78 // update.module sets a different project type
79 // for disabled projects. Here we normalize it.
80 if ($check_disabled) {
81 foreach ($update_info as $key => $project) {
82 if (in_array($project['project_type'], array('module-disabled', 'theme-disabled'))) {
83 $update_info[$key]['project_type'] = substr($project['project_type'], 0, strpos($project['project_type'], '-'));
90 * Obtains release info for all installed projects via update.module.
92 * @see update_get_available().
93 * @see \Drupal\update\Controller\UpdateController::updateStatusManually()
95 protected function getAvailableReleases() {
96 // Force to invalidate some caches that are only cleared
97 // when visiting update status report page. This allow to detect changes in
99 \Drupal::keyValueExpirable('update')->deleteMultiple(array('update_project_projects', 'update_project_data'));
101 // From update_get_available(): Iterate all projects and create a fetch task
102 // for those we have no information or is obsolete.
103 $available = \Drupal::keyValueExpirable('update_available_releases')->getAll();
104 $update_projects = \Drupal::service('update.manager')->getProjects();
105 foreach ($update_projects as $key => $project) {
106 if (empty($available[$key])) {
107 \Drupal::service('update.processor')->createFetchTask($project);
110 if ($project['info']['_info_file_ctime'] > $available[$key]['last_fetch']) {
111 $available[$key]['fetch_status'] = UPDATE_FETCH_PENDING;
113 if (empty($available[$key]['releases'])) {
114 $available[$key]['fetch_status'] = UPDATE_FETCH_PENDING;
116 if (!empty($available[$key]['fetch_status']) && $available[$key]['fetch_status'] == UPDATE_FETCH_PENDING) {
117 \Drupal::service('update.processor')->createFetchTask($project);
121 // Set a batch to process all pending tasks.
123 'operations' => array(
124 array(array(\Drupal::service('update.manager'), 'fetchDataBatch'), array()),
126 'finished' => 'update_fetch_data_finished',
127 'file' => drupal_get_path('module', 'update') . '/update.fetch.inc',
130 drush_backend_batch_process();
132 // Clear any error set by a failed update fetch task. This avoid rollbacks.
135 return \Drupal::keyValueExpirable('update_available_releases')->getAll();
139 * Calculates update status for all projects via update.module.
141 protected function calculateUpdateStatus($available, $projects) {
142 module_load_include('inc', 'update', 'update.compare');
143 $data = update_calculate_project_data($available);
145 foreach ($data as $project_name => $project) {
146 // Discard custom projects.
147 if ($project['status'] == UPDATE_UNKNOWN) {
148 unset($data[$project_name]);
151 // Discard projects with unknown installation path.
152 if ($project_name != 'drupal' && !isset($projects[$project_name]['path'])) {
153 unset($data[$project_name]);
157 // Add some info from the project to $data.
158 $data[$project_name] += array(
159 'path' => isset($projects[$project_name]['path']) ? $projects[$project_name]['path'] : '',
160 'label' => $projects[$project_name]['label'],
162 // Store all releases, not just the ones selected by update.module.
163 // We use it to allow the user to update to a specific version.
164 if (isset($available[$project_name]['releases'])) {
165 $data[$project_name]['releases'] = $available[$project_name]['releases'];