automatic_updates.module in Automatic Updates 8
Same filename and directory in other branches
Contains automatic_updates.module..
File
automatic_updates.moduleView source
<?php
/**
* @file
* Contains automatic_updates.module..
*/
use Drupal\automatic_updates\ReadinessChecker\ReadinessCheckerManagerInterface;
use Drupal\automatic_updates\UpdateMetadata;
use Drupal\Core\Url;
use Drupal\update\UpdateManagerInterface;
use Symfony\Component\Process\PhpExecutableFinder;
use Symfony\Component\Process\Process;
/**
* Implements hook_page_top().
*/
function automatic_updates_page_top(array &$page_top) {
/** @var \Drupal\Core\Routing\AdminContext $admin_context */
$admin_context = \Drupal::service('router.admin_context');
$route_match = \Drupal::routeMatch();
if ($admin_context
->isAdminRoute($route_match
->getRouteObject()) && \Drupal::currentUser()
->hasPermission('administer site configuration')) {
$disabled_routes = [
'update.theme_update',
'system.theme_install',
'update.module_update',
'update.module_install',
'update.status',
'update.report_update',
'update.report_install',
'update.settings',
'system.status',
'update.confirmation_page',
];
// These routes don't need additional nagging.
if (in_array(\Drupal::routeMatch()
->getRouteName(), $disabled_routes, TRUE)) {
return;
}
/** @var \Drupal\automatic_updates\Services\AutomaticUpdatesPsaInterface $psa */
$psa = \Drupal::service('automatic_updates.psa');
$messages = $psa
->getPublicServiceMessages();
if ($messages) {
\Drupal::messenger()
->addError(t('Public service announcements:'));
foreach ($messages as $message) {
\Drupal::messenger()
->addError($message);
}
}
$last_check_timestamp = \Drupal::service('automatic_updates.readiness_checker')
->timestamp();
if (\Drupal::time()
->getRequestTime() > $last_check_timestamp + ReadinessCheckerManagerInterface::LAST_CHECKED_WARNING) {
$readiness_settings = Url::fromRoute('automatic_updates.settings');
\Drupal::messenger()
->addError(t('Your site has not recently run an update readiness check. <a href="@link">Administer automatic updates</a> and run readiness checks manually.', [
'@link' => $readiness_settings
->toString(),
]));
}
/** @var \Drupal\automatic_updates\ReadinessChecker\ReadinessCheckerManagerInterface $checker */
$checker = \Drupal::service('automatic_updates.readiness_checker');
$results = $checker
->getResults(ReadinessCheckerManagerInterface::ERROR);
if ($results) {
\Drupal::messenger()
->addError(t('Your site is currently failing readiness checks for automatic updates. It cannot be <a href="@readiness_checks">automatically updated</a> until further action is performed:', [
'@readiness_checks' => 'https://www.drupal.org/docs/8/update/automatic-updates#readiness-checks',
]));
foreach ($results as $message) {
\Drupal::messenger()
->addError($message);
}
}
$results = $checker
->getResults('warning');
if ($results) {
\Drupal::messenger()
->addWarning(t('Your site does not pass some readiness checks for automatic updates. Depending on the nature of the failures, it might effect the eligibility for <a href="@readiness_checks">automatic updates</a>.', [
'@readiness_checks' => 'https://www.drupal.org/docs/8/update/automatic-updates#readiness-checks',
]));
foreach ($results as $message) {
\Drupal::messenger()
->addWarning($message);
}
}
}
}
/**
* Implements hook_cron().
*/
function automatic_updates_cron() {
$state = \Drupal::state();
$request_time = \Drupal::time()
->getRequestTime();
$last_check = $state
->get('automatic_updates.cron_last_check', 0);
// Only allow cron to run once every hour.
if ($request_time - $last_check < 3600) {
return;
}
// Checkers should run before updates because of class caching.
/** @var \Drupal\automatic_updates\Services\NotifyInterface $notify */
$notify = \Drupal::service('automatic_updates.psa_notify');
$notify
->send();
/** @var \Drupal\automatic_updates\ReadinessChecker\ReadinessCheckerManagerInterface $checker */
$checker = \Drupal::service('automatic_updates.readiness_checker');
foreach ($checker
->getCategories() as $category) {
$checker
->run($category);
}
// In-place updates won't function for dev releases of Drupal core.
$dev_core = strpos(\Drupal::VERSION, '-dev') !== FALSE;
/** @var \Drupal\Core\Config\ImmutableConfig $config */
$config = \Drupal::config('automatic_updates.settings');
if (!$dev_core && $config
->get('enable_cron_updates')) {
\Drupal::service('update.manager')
->refreshUpdateData();
\Drupal::service('update.processor')
->fetchData();
$available = update_get_available(TRUE);
$projects = update_calculate_project_data($available);
$not_recommended_version = $projects['drupal']['status'] !== UpdateManagerInterface::CURRENT;
$security_update = in_array($projects['drupal']['status'], [
UpdateManagerInterface::NOT_SECURE,
UpdateManagerInterface::REVOKED,
], TRUE);
$recommended_release = isset($projects['drupal']['releases'][$projects['drupal']['recommended']]) ? $projects['drupal']['releases'][$projects['drupal']['recommended']] : NULL;
$existing_minor_version = explode('.', \Drupal::VERSION, -1);
$recommended_minor_version = explode('.', $recommended_release['version'], -1);
$major_upgrade = $existing_minor_version !== $recommended_minor_version;
if ($major_upgrade) {
foreach (range(1, 30) as $point_version) {
$potential_version = implode('.', array_merge($existing_minor_version, (array) $point_version));
if (isset($available['drupal']['releases'][$potential_version])) {
$recommended_release = $available['drupal']['releases'][$potential_version];
}
else {
break;
}
}
}
// Don't automatically update major version bumps or from/to same version.
if ($not_recommended_version && $projects['drupal']['existing_version'] !== $recommended_release['version']) {
if ($config
->get('enable_cron_security_updates')) {
if ($security_update) {
$metadata = new UpdateMetadata('drupal', 'core', \Drupal::VERSION, $recommended_release['version']);
/** @var \Drupal\automatic_updates\Services\UpdateInterface $updater */
$updater = \Drupal::service('automatic_updates.update');
$updater
->update($metadata);
}
}
else {
$metadata = new UpdateMetadata('drupal', 'core', \Drupal::VERSION, $recommended_release['version']);
/** @var \Drupal\automatic_updates\Services\UpdateInterface $updater */
$updater = \Drupal::service('automatic_updates.update');
$updater
->update($metadata);
}
}
}
$state
->set('automatic_updates.cron_last_check', \Drupal::time()
->getCurrentTime());
}
/**
* Implements hook_theme().
*/
function automatic_updates_theme(array $existing, $type, $theme, $path) {
return [
'automatic_updates_psa_notify' => [
'variables' => [
'messages' => [],
],
],
'automatic_updates_post_update' => [
'variables' => [
'success' => NULL,
'metadata' => NULL,
],
],
];
}
/**
* Implements hook_mail().
*/
function automatic_updates_mail($key, &$message, $params) {
/** @var \Drupal\Core\Render\RendererInterface $renderer */
$renderer = \Drupal::service('renderer');
$message['subject'] = $params['subject'];
$message['body'][] = $renderer
->render($params['body']);
}
/**
* Helper method to execute console command.
*
* @param string $command_argument
* The command argument.
*
* @return \Symfony\Component\Process\Process
* The console command process.
*/
function automatic_updates_console_command($command_argument) {
$module_path = drupal_get_path('module', 'automatic_updates');
$command = [
(new PhpExecutableFinder())
->find(),
$module_path . '/scripts/automatic_update_tools',
$command_argument,
'--script-filename',
\Drupal::request()->server
->get('SCRIPT_FILENAME'),
'--base-url',
\Drupal::request()
->getBaseUrl(),
'--base-path',
\Drupal::request()
->getBasePath(),
];
$process = new Process($command, (string) \Drupal::root(), NULL, NULL, NULL);
$process
->run();
return $process;
}
Functions
Name | Description |
---|---|
automatic_updates_console_command | Helper method to execute console command. |
automatic_updates_cron | Implements hook_cron(). |
automatic_updates_mail | Implements hook_mail(). |
automatic_updates_page_top | Implements hook_page_top(). |
automatic_updates_theme | Implements hook_theme(). |