View source
<?php
namespace Drupal\config_update_ui\Controller;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Diff\DiffFormatter;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Extension\ThemeHandlerInterface;
use Drupal\Core\Site\Settings;
use Drupal\Core\Url;
use Drupal\config_update\ConfigDiffInterface;
use Drupal\config_update\ConfigListByProviderInterface;
use Drupal\config_update\ConfigRevertInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class ConfigUpdateController extends ControllerBase {
protected $configDiff;
protected $configList;
protected $configRevert;
protected $diffFormatter;
protected $moduleHandler;
protected $themeHandler;
protected $configFactory;
public function __construct(ConfigDiffInterface $config_diff, ConfigListByProviderInterface $config_list, ConfigRevertInterface $config_update, DiffFormatter $diff_formatter, ModuleHandlerInterface $module_handler, ThemeHandlerInterface $theme_handler, ConfigFactoryInterface $config_factory) {
$this->configDiff = $config_diff;
$this->configList = $config_list;
$this->configRevert = $config_update;
$this->diffFormatter = $diff_formatter;
$this->diffFormatter->show_header = FALSE;
$this->moduleHandler = $module_handler;
$this->themeHandler = $theme_handler;
$this->configFactory = $config_factory;
}
public static function create(ContainerInterface $container) {
return new static($container
->get('config_update.config_diff'), $container
->get('config_update.config_list'), $container
->get('config_update.config_update'), $container
->get('diff.formatter'), $container
->get('module_handler'), $container
->get('theme_handler'), $container
->get('config.factory'));
}
public function diff($config_type, $config_name) {
$diff = $this->configDiff
->diff($this->configRevert
->getFromExtension($config_type, $config_name), $this->configRevert
->getFromActive($config_type, $config_name));
$build = [];
$definition = $this->configList
->getType($config_type);
$config_type_label = $definition ? $definition
->getLabel() : $this
->t('Simple configuration');
$build['#title'] = $this
->t('Config difference for @type @name', [
'@type' => $config_type_label,
'@name' => $config_name,
]);
$build['#attached']['library'][] = 'system/diff';
$build['diff'] = [
'#type' => 'table',
'#header' => [
[
'data' => $this
->t('Source config'),
'colspan' => '2',
],
[
'data' => $this
->t('Site config'),
'colspan' => '2',
],
],
'#rows' => $this->diffFormatter
->format($diff),
'#attributes' => [
'class' => [
'diff',
],
],
];
$url = new Url('config_update_ui.report');
$build['back'] = [
'#type' => 'link',
'#attributes' => [
'class' => [
'dialog-cancel',
],
],
'#title' => $this
->t("Back to 'Updates report' page."),
'#url' => $url,
];
return $build;
}
public function report($report_type = NULL, $name = NULL) {
$links = $this
->generateReportLinks();
$report = $this
->generateReport($report_type, $name);
if (!$report) {
return $links;
}
$build = [];
$build['#title'] = $report['#title'];
unset($report['#title']);
$build['links_wrapper'] = [
'#type' => 'details',
'#title' => $this
->t('Generate new report'),
'#children' => $links,
];
$build['report'] = $report;
$build['#attached']['library'][] = 'config_update/report_css';
return $build;
}
protected function generateReportLinks() {
$build = [];
$build['links'] = [
'#type' => 'table',
'#header' => [
$this
->t('Report type'),
$this
->t('Report on'),
],
'#rows' => [],
];
$links['report_full'] = [
'title' => $this
->t('Everything'),
'url' => Url::fromRoute('config_update_ui.report', [
'report_type' => 'type',
'name' => 'system.all',
]),
];
$build['links']['#rows'][] = [
$this
->t('Full report'),
[
'data' => [
'#type' => 'operations',
'#links' => $links,
],
],
];
$definitions = $this->configList
->listTypes();
$links = [];
foreach ($definitions as $entity_type => $definition) {
$links['report_type_' . $entity_type] = [
'title' => $definition
->getLabel(),
'url' => Url::fromRoute('config_update_ui.report', [
'report_type' => 'type',
'name' => $entity_type,
]),
];
}
uasort($links, [
$this,
'sortLinks',
]);
$links = [
'report_type_system.simple' => [
'title' => $this
->t('Simple configuration'),
'url' => Url::fromRoute('config_update_ui.report', [
'report_type' => 'type',
'name' => 'system.simple',
]),
],
] + $links;
$build['links']['#rows'][] = [
$this
->t('Single configuration type'),
[
'data' => [
'#type' => 'operations',
'#links' => $links,
],
],
];
$profile = $this
->getProfileName();
$modules = $this->moduleHandler
->getModuleList();
$links = [];
foreach ($modules as $machine_name => $module) {
if ($machine_name != $profile && $this->configList
->providerHasConfig('module', $machine_name)) {
$links['report_module_' . $machine_name] = [
'title' => $this->moduleHandler
->getName($machine_name),
'url' => Url::fromRoute('config_update_ui.report', [
'report_type' => 'module',
'name' => $machine_name,
]),
];
}
}
uasort($links, [
$this,
'sortLinks',
]);
$build['links']['#rows'][] = [
$this
->t('Single module'),
[
'data' => [
'#type' => 'operations',
'#links' => $links,
],
],
];
$themes = $this->themeHandler
->listInfo();
$links = [];
foreach ($themes as $machine_name => $theme) {
if ($this->configList
->providerHasConfig('theme', $machine_name)) {
$links['report_theme_' . $machine_name] = [
'title' => $this->themeHandler
->getName($machine_name),
'url' => Url::fromRoute('config_update_ui.report', [
'report_type' => 'theme',
'name' => $machine_name,
]),
];
}
}
uasort($links, [
$this,
'sortLinks',
]);
$build['links']['#rows'][] = [
$this
->t('Single theme'),
[
'data' => [
'#type' => 'operations',
'#links' => $links,
],
],
];
$links = [];
if ($this->configList
->providerHasConfig('profile', $profile)) {
$links['report_profile_' . $profile] = [
'title' => $this->moduleHandler
->getName($profile),
'url' => Url::fromRoute('config_update_ui.report', [
'report_type' => 'profile',
]),
];
$build['links']['#rows'][] = [
$this
->t('Installation profile'),
[
'data' => [
'#type' => 'operations',
'#links' => $links,
],
],
];
}
return $build;
}
protected function generateReport($report_type, $value) {
switch ($report_type) {
case 'type':
if ($value == 'system.all') {
$label = $this
->t('All configuration');
}
elseif ($value == 'system.simple') {
$label = $this
->t('Simple configuration');
}
else {
$definition = $this->configList
->getType($value);
if (!$definition) {
return NULL;
}
$label = $this
->t('@name configuration', [
'@name' => $definition
->getLabel(),
]);
}
break;
case 'module':
$list = $this->moduleHandler
->getModuleList();
if (!isset($list[$value])) {
return NULL;
}
$label = $this
->t('@name module', [
'@name' => $this->moduleHandler
->getName($value),
]);
break;
case 'theme':
$list = $this->themeHandler
->listInfo();
if (!isset($list[$value])) {
return NULL;
}
$label = $this
->t('@name theme', [
'@name' => $this->themeHandler
->getName($value),
]);
break;
case 'profile':
$profile = $this
->getProfileName();
$label = $this
->t('@name profile', [
'@name' => $this->moduleHandler
->getName($profile),
]);
break;
default:
return NULL;
}
list($active_list, $install_list, $optional_list) = $this->configList
->listConfig($report_type, $value);
$build = [];
$build['#title'] = $this
->t('Configuration updates report for @label', [
'@label' => $label,
]);
$build['report_header'] = [
'#markup' => '<h3>' . $this
->t('Updates report') . '</h3>',
];
$removed = array_diff($install_list, $active_list);
$build['removed'] = [
'#caption' => $this
->t('Missing configuration items'),
'#empty' => $this
->t('None: all provided configuration items are in your active configuration.'),
] + $this
->makeReportTable($removed, 'extension', [
'import',
]);
$inactive = array_diff($optional_list, $active_list);
$build['inactive'] = [
'#caption' => $this
->t('Inactive optional items'),
'#empty' => $this
->t('None: all optional configuration items are in your active configuration.'),
] + $this
->makeReportTable($inactive, 'extension', [
'import',
]);
$added = array_diff($active_list, $install_list, $optional_list);
if ($report_type == 'type') {
$build['added'] = [
'#caption' => $this
->t('Added configuration items'),
'#empty' => $this
->t('None: all active configuration items of this type were provided by modules, themes, or install profile.'),
] + $this
->makeReportTable($added, 'active', [
'export',
'delete',
]);
}
$both = array_diff($active_list, $added);
$different = [];
foreach ($both as $name) {
if (!$this->configDiff
->same($this->configRevert
->getFromExtension('', $name), $this->configRevert
->getFromActive('', $name))) {
$different[] = $name;
}
}
$build['different'] = [
'#caption' => $this
->t('Changed configuration items'),
'#empty' => $this
->t('None: no active configuration items differ from their current provided versions.'),
] + $this
->makeReportTable($different, 'active', [
'diff',
'export',
'revert',
]);
return $build;
}
protected function makeReportTable(array $names, $storage, array $actions) {
$build = [];
$build['#type'] = 'table';
$build['#attributes'] = [
'class' => [
'config-update-report',
],
];
$build['#header'] = [
'name' => [
'data' => $this
->t('Machine name'),
],
'label' => [
'data' => $this
->t('Label (if any)'),
'class' => [
RESPONSIVE_PRIORITY_LOW,
],
],
'type' => [
'data' => $this
->t('Type'),
'class' => [
RESPONSIVE_PRIORITY_MEDIUM,
],
],
'provider' => [
'data' => $this
->t('Provider'),
'class' => [
RESPONSIVE_PRIORITY_LOW,
],
],
'operations' => [
'data' => $this
->t('Operations'),
],
];
$build['#rows'] = [];
foreach ($names as $name) {
$row = [];
if ($storage == 'active') {
$config = $this->configRevert
->getFromActive('', $name);
}
else {
$config = $this->configRevert
->getFromExtension('', $name);
}
$entity_type = $this->configList
->getTypeNameByConfigName($name);
if (!$entity_type) {
$id = $name;
$label = '';
$type_label = $this
->t('Simple configuration');
$entity_type = 'system.simple';
}
else {
$definition = $this->configList
->getType($entity_type);
$id_key = $definition
->getKey('id');
$id = $config[$id_key];
if ($label_key = $definition
->getKey('label')) {
$label = $config[$label_key];
}
else {
$label = '';
}
$type_label = $definition
->getLabel();
}
$row[] = $name;
$row[] = $label;
$row[] = $type_label;
$provider = $this->configList
->getConfigProvider($name);
$provider_name = '';
if (!empty($provider)) {
switch ($provider[0]) {
case 'profile':
$provider_name = $this->moduleHandler
->getName($provider[1]);
if ($provider_name) {
$provider_name = $this
->t('@name profile', [
'@name' => $provider_name,
]);
}
else {
$provider_name = '';
}
break;
case 'module':
$provider_name = $this->moduleHandler
->getName($provider[1]);
if ($provider_name) {
$provider_name = $this
->t('@name module', [
'@name' => $provider_name,
]);
}
else {
$provider_name = '';
}
break;
case 'theme':
$provider_name = $this->themeHandler
->getName($provider[1]);
if ($provider_name) {
$provider_name = $this
->t('@name theme', [
'@name' => $provider_name,
]);
}
else {
$provider_name = '';
}
break;
}
}
$row[] = $provider_name;
$links = [];
$routes = [
'export' => 'config.export_single',
'import' => 'config_update_ui.import',
'diff' => 'config_update_ui.diff',
'revert' => 'config_update_ui.revert',
'delete' => 'config_update_ui.delete',
];
$titles = [
'export' => $this
->t('Export'),
'import' => $this
->t('Import from source'),
'diff' => $this
->t('Show differences'),
'revert' => $this
->t('Revert to source'),
'delete' => $this
->t('Delete'),
];
foreach ($actions as $action) {
$links[$action] = [
'url' => Url::fromRoute($routes[$action], [
'config_type' => $entity_type,
'config_name' => $id,
]),
'title' => $titles[$action],
];
}
$row[] = [
'data' => [
'#type' => 'operations',
'#links' => $links,
],
];
$build['#rows'][] = $row;
}
return $build;
}
protected static function sortLinks($link1, $link2) {
$title1 = $link1['title'];
$title2 = $link2['title'];
if ($title1 == $title2) {
return 0;
}
return $title1 < $title2 ? -1 : 1;
}
protected function getProfileName() {
$profile = $this->configFactory
->get('core.extension')
->get('profile');
if (!empty($profile)) {
return $profile;
}
else {
return Settings::get('install_profile');
}
}
}