Skip to content
Snippets Groups Projects
Commit 7939f672 authored by Ted Bowman's avatar Ted Bowman
Browse files

remove all but info file

parent db52041a
No related branches found
No related tags found
No related merge requests found
<?php
/**
* @file
*
*/
use Drupal\aue\UpdateSettingFormAlterer;
/**
* Implements hook_form_FORM_ID_alter().
*/
function aue_form_update_settings_alter(&$form, &$form_state): void {
/** @var \Drupal\Core\DependencyInjection\ClassResolverInterface $class_resolver **/
$class_resolver = \Drupal::service('class_resolver');
$class_resolver->getInstanceFromDefinition(UpdateSettingFormAlterer::class)->alter($form, $form_state);
}
unattended:
method: web
level: disable
allow_core_minor_updates: false
status_check_mail: errors_only
aue.settings:
type: config_object
label: 'Automatic Updates Extra settings'
mapping:
unattended:
type: mapping
label: 'Settings for unattended update'
mapping:
level:
type: string
label: 'Which level of unattended updates to perform'
constraints:
NotNull: []
Choice: [disable, security, patch, custom]
projects:
type: mapping
label: 'Projects'
mapping:
'*':
type: string
label: 'level'
excluded_projects:
type: sequence
label: 'Excluded projects'
sequence:
type: string
cron_port:
type: integer
label: 'Port to use for finalization sub-request'
<?php
namespace Drupal\aue;
use Drupal\package_manager\StageBase;
use Symfony\Component\Console\Output\OutputInterface;
class ContribConsoleUpdateStage extends StageBase {
/**
* {@inheritdoc}
*/
protected string $type = 'aue:unattended';
/**
* The metadata key that stores the previous and target versions of core.
*
* @see ::handlePostApply()
*
* @var string
*/
protected const VERSIONS_METADATA_KEY = 'aue_versions';
/**
* The console output handler.
*
* @see ::triggerPostApply()
*
* @var \Symfony\Component\Console\Output\OutputInterface
*/
public OutputInterface $output;
/**
* Whether the update is being triggered by a web request.
*
* @see ::triggerPostApply()
*
* @var bool
*/
public bool $isFromWeb = FALSE;
}
<?php
declare(strict_types = 1);
namespace Drupal\aue;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\CronInterface;
use Drupal\Core\Utility\Error;
use Drupal\package_manager\PathLocator;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait;
use Psr\Log\NullLogger;
/**
* Runs updates as a detached background process after regular cron tasks.
*
* The update process will be started in a detached process which will continue
* running after the web request has terminated. This is done after the
* decorated cron service has been called, so regular cron tasks will always be
* run regardless of whether there is an update available and whether an update
* is successful.
*
* @internal
* This class implements logic specific to Automatic Updates' cron hook
* implementation and may be changed or removed at any time without warning.
* It should not be called directly, and external code should not interact
* with it.
*/
class CronUpdateRunner implements CronInterface, LoggerAwareInterface {
use LoggerAwareTrait;
/**
* The current interface between PHP and the server.
*
* @var string
*/
private static $serverApi = PHP_SAPI;
/**
* All automatic updates are disabled.
*
* @var string
*/
public const DISABLED = 'disable';
/**
* Only perform automatic security updates.
*
* @var string
*/
public const SECURITY = 'security';
/**
* All patch automatic updates are enabled.
*
* @var string
*/
public const PATCH = 'patch';
/**
* Custom updates for each project.
*
* @var string
*/
public const CUSTOM = 'custom';
/**
* Constructs a CronUpdateRunner object.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
* The config factory service.
* @param \Drupal\package_manager\PathLocator $pathLocator
* The path locator service.
* @param \Drupal\Core\CronInterface $inner
* The decorated cron service.
* @param \Drupal\automatic_updates\CommandExecutor $commandExecutor
* The update command executor service.
*/
public function __construct(
private readonly ConfigFactoryInterface $configFactory,
private readonly PathLocator $pathLocator,
private readonly CronInterface $inner,
private readonly CommandExecutor $commandExecutor,
) {
$this->setLogger(new NullLogger());
}
/**
* Runs the terminal update command.
*/
protected function runTerminalUpdateCommand(): void {
// Use the `&` on the command line to detach this process after it is
// started. This will allow the command to outlive the web request.
$process = $this->commandExecutor->create('--is-from-web &');
try {
$pid = $this->commandExecutor->start($process);
}
catch (\Throwable $throwable) {
Error::logException($this->logger, $throwable, 'Unable to start background update.');
}
if ($process->isTerminated()) {
if ($process->getExitCode() !== 0) {
$this->logger->error('Background update failed: %message', [
'%message' => $process->getErrorOutput(),
]);
}
}
elseif (empty($pid)) {
$this->logger->error('Background update failed because the process did not start within 5 seconds.');
}
}
/**
* Indicates if we are currently running at the command line.
*
* @return bool
* TRUE if we are running at the command line, otherwise FALSE.
*/
final public static function isCommandLine(): bool {
return self::$serverApi === 'cli';
}
/**
* {@inheritdoc}
*/
public function run() {
// Always run the cron service before we trigger the update terminal
// command.
$decorated_cron_succeeded = $this->inner->run();
$method = $this->configFactory->get('automatic_updates.settings')
->get('unattended.method');
// If we are configured to run updates via the web, and we're actually being
// accessed via the web (i.e., anything that isn't the command line), go
// ahead and try to do the update.
if ($method === 'web' && !self::isCommandLine()) {
$this->runTerminalUpdateCommand();
}
return $decorated_cron_succeeded;
}
/**
* Gets the cron update mode.
*
* @return string
* The cron update mode. Will be one of the following constants:
* - self::DISABLED if updates during
* cron are entirely disabled.
* - self::SECURITY only security
* updates can be done during cron.
* - self::ALL if all updates are
* allowed during cron.
*/
final public function getMode(): string {
$mode = $this->configFactory->get('automatic_updates.settings')->get('unattended.level');
return $mode ?: static::SECURITY;
}
}
<?php
namespace Drupal\aue;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Extension\ModuleExtensionList;
use Drupal\Core\Extension\ThemeExtensionList;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class UpdateSettingFormAlterer implements ContainerInjectionInterface {
public function __construct(private ModuleExtensionList $moduleList, private ThemeExtensionList $themeList) {
}
/**
* @inheritDoc
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('extension.list.module'),
$container->get('extension.list.theme')
);
}
/**
* Alters the update settings form.
*
* @param array $form
* The form array.
* @param array $form_state
* The form state array.
*/
public function alter(array &$form, FormStateInterface &$form_state): void {
// Get the aue.aue.settings configuration.
$config = \Drupal::configFactory()->get('aue.settings');
$form['aue'] = [
'#type' => 'fieldset',
'#title' => t('Contrib background updates'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#weight' => 50,
];
$form['aue']['unattended_level'] = [
'#type' => 'radios',
'#title' => t('Update level'),
'#options' => [
CronUpdateRunner::DISABLED => t('Disabled'),
CronUpdateRunner::SECURITY => t('Security updates only'),
CronUpdateRunner::PATCH => t('All patch releases'),
CronUpdateRunner::CUSTOM => t('Select the updates for each of your projects'),
],
'#default_value' => $config->get('unattended.level'),
'#description' => t('When background updates are applied, your site will be briefly put into maintenance mode.'),
];
$enabled_projects = $this->getEnabledProjects();
$states_excluded = [
'visible' => [
'input[name="unattended_level"]' => [
// only visible when either patch or security is selected
['value' => CronUpdateRunner::SECURITY],
['value' => CronUpdateRunner::PATCH],
],
],
];
$states_custom = [
'visible' => [
'input[name="unattended_level"]' => [
'value' => CronUpdateRunner::CUSTOM,
],
],
];
// in a new fieldset create a select block for each project. The options
// for each checkbox for each project will be same as for unattended_level
// radio buttons except the custom option.
$form['aue']['unattended_custom'] = [
'#type' => 'fieldset',
'#title' => t('Custom update level'),
'#states' => $states_custom,
];
foreach ($enabled_projects as $project) {
$form['aue']['unattended_custom'][$project] = [
'#type' => 'select',
'#title' => t('Update level for %project', ['%project' => $project]),
'#options' => [
CronUpdateRunner::DISABLED => t('Disabled'),
CronUpdateRunner::SECURITY => t('Security updates only'),
CronUpdateRunner::PATCH => t('All patch releases'),
],
//'#default_value' => $config->get('unattended.custom.' . $project),
'#states' => $states_custom,
];
}
foreach ($enabled_projects as $project) {
$form['aue']['unattended_custom'][$project] = [
'#type' => 'select',
'#title' => t('Update level for %project', ['%project' => $project]),
'#options' => [
CronUpdateRunner::DISABLED => t('Disabled'),
CronUpdateRunner::SECURITY => t('Security updates only'),
CronUpdateRunner::PATCH => t('All patch releases'),
],
//'#default_value' => $config->get('unattended.custom.' . $project),
'#states' => [
'visible' => [
'input[name="unattended_level"]' => [
'value' => CronUpdateRunner::CUSTOM,
],
],
],
];
}
$form['aue']['excluded'] = [
'#type' => 'fieldset',
'#title' => t('Excluded projects'),
'#states' => $states_excluded,
];
foreach ($enabled_projects as $project) {
$form['aue']['excluded'][$project] = [
'#type' => 'checkbox',
'#title' => t('Exclude %project from automatic updates', ['%project' => $project]),
'#default_value' => $config->get('excluded.' . $project),
'#states' => $states_excluded,
];
}
$form['aue']['unattended_method'] = [
'#type' => 'radios',
'#title' => t('How unattended updates should be run'),
'#options' => [
'web' => t('By using the Automated Cron module or a request to /system/cron'),
'console' => t('By the <code>auto-update</code> command-line utility'),
],
'#default_value' => $config->get('unattended.method'),
'#states' => [
'invisible' => [
'input[name="unattended_level"]' => [
'value' => CronUpdateRunner::DISABLED,
],
],
],
'#description' => t('To use the <code>/system/cron</code> method <a href="http://drupal.org/docs/user_guide/en/security-cron.html">ensure cron is set up correctly</a>.'),
];
$form['#submit'][] = '_automatic_updates_submit_update_settings';
}
/**
* Gets projects that ccontain an enabled module or theme.
*
* @return string[]
*/
private function getEnabledProjects(): array {
$enabled_projects = [];
$installed_extensions = array_merge($this->moduleList->getAllInstalledInfo(), $this->themeList->getAllInstalledInfo());
foreach ($installed_extensions as $extension_name => $info) {
if (isset($info['project']) && !isset($enabled_projects[$info['project']])) {
$enabled_projects[] = $info['project'];
}
}
return $enabled_projects;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment