View source
<?php
namespace Drupal\config_inspector\Controller;
use Drupal\config_inspector\ConfigInspectorManager;
use Drupal\Core\Config\Schema\ArrayElement;
use Drupal\Core\Config\StorageInterface;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Link;
use Drupal\Component\Serialization\Yaml;
use Drupal\Core\StringTranslation\TranslationManager;
use Drupal\Core\TypedData\TypedDataInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Response;
class ConfigInspectorController extends ControllerBase {
protected $configStorage;
protected $configInspectorManager;
protected $translationManager;
protected $formBuilder;
protected $moduleHandler;
protected $dumper;
public function __construct(StorageInterface $storage, ConfigInspectorManager $config_inspector_manager, TranslationManager $translation_manager, FormBuilderInterface $form_builder, ModuleHandlerInterface $module_handler) {
$this->configStorage = $storage;
$this->configInspectorManager = $config_inspector_manager;
$this->translationManager = $translation_manager;
$this->formBuilder = $form_builder;
$this->moduleHandler = $module_handler;
}
public static function create(ContainerInterface $container) {
$form = new static($container
->get('config.storage'), $container
->get('plugin.manager.config_inspector'), $container
->get('string_translation'), $container
->get('form_builder'), $container
->get('module_handler'));
if ($container
->has('devel.dumper')) {
$form->dumper = $container
->get('devel.dumper');
}
return $form;
}
public function overview() {
$page['#attached']['library'][] = 'system/drupal.debounce';
$page['#attached']['library'][] = 'config_inspector/config_inspector';
$page['filters'] = [
'#type' => 'container',
'#attributes' => [
'class' => [
'table-filter',
'js-show',
],
],
];
$page['filters']['text'] = [
'#type' => 'search',
'#title' => $this
->t('Search'),
'#size' => 30,
'#placeholder' => $this
->t('Search for a configuration key'),
'#attributes' => [
'id' => 'schema-filter-text',
'autocomplete' => 'off',
'title' => $this
->t('Enter a part of the configuration key to filter by.'),
],
];
$page['filters']['schema_has_errors'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Only show errors'),
'#label_attributes' => [
'for' => 'schema-has-errors',
],
'#attributes' => [
'id' => 'schema-has-errors',
],
];
$page['table'] = [
'#type' => 'table',
'#header' => [
'name' => $this
->t('Configuration key'),
'schema' => $this
->t('Schema'),
'list' => $this
->t('List'),
'tree' => $this
->t('Tree'),
'form' => $this
->t('Form'),
'raw' => $this
->t('Raw data'),
'download' => $this
->t('Download'),
],
'#attributes' => [
'class' => [
'config-inspector-list',
],
],
];
foreach ($this->configStorage
->listAll() as $name) {
$label = '<span class="table-filter-text-source">' . $name . '</span>';
if (!$this->configInspectorManager
->hasSchema($name)) {
$page['table'][] = [
'name' => [
'#markup' => $label,
],
'schema' => [
'#markup' => $this
->t('None'),
'#wrapper_attributes' => [
'data-has-errors' => TRUE,
],
],
'list' => [
'#markup' => $this
->t('N/A'),
],
'tree' => [
'#markup' => $this
->t('N/A'),
],
'form' => [
'#markup' => $this
->t('N/A'),
],
'raw' => Link::createFromRoute($this
->t('Raw data'), 'config_inspector.raw_page', [
'name' => $name,
])
->toRenderable(),
'download' => Link::createFromRoute($this
->t('Download'), 'config_inspector.download', [
'name' => $name,
])
->toRenderable(),
];
}
else {
$schema = $this
->t('Correct');
$result = $this->configInspectorManager
->checkValues($name);
if (is_array($result)) {
$schema = $this->translationManager
->formatPlural(count($result), '@count error', '@count errors');
}
$page['table'][] = [
'name' => [
'#markup' => $label,
],
'schema' => [
'#markup' => $schema,
'#wrapper_attributes' => [
'data-has-errors' => is_array($result),
],
],
'list' => [
'#markup' => Link::createFromRoute($this
->t('List'), 'config_inspector.list_page', [
'name' => $name,
])
->toString(),
],
'tree' => [
'#markup' => Link::createFromRoute($this
->t('Tree'), 'config_inspector.tree_page', [
'name' => $name,
])
->toString(),
],
'form' => [
'#markup' => Link::createFromRoute($this
->t('Form'), 'config_inspector.form_page', [
'name' => $name,
])
->toString(),
],
'raw' => [
'#markup' => Link::createFromRoute($this
->t('Raw data'), 'config_inspector.raw_page', [
'name' => $name,
])
->toString(),
],
'download' => [
'#markup' => Link::createFromRoute($this
->t('Download'), 'config_inspector.download', [
'name' => $name,
])
->toString(),
],
];
}
}
return $page;
}
public function getList($name) {
$config_schema = $this->configInspectorManager
->getConfigSchema($name);
$output = $this
->formatList($name, $config_schema);
$output['#title'] = $this
->t('List of configuration data for %name', [
'%name' => $name,
]);
return $output;
}
public function getTree($name) {
$config_schema = $this->configInspectorManager
->getConfigSchema($name);
$output = $this
->formatTree($config_schema);
$output['#title'] = $this
->t('Tree of configuration data for %name', [
'%name' => $name,
]);
return $output;
}
public function getForm($name) {
$config_schema = $this->configInspectorManager
->getConfigSchema($name);
$output = $this->formBuilder
->getForm('\\Drupal\\config_inspector\\Form\\ConfigInspectorItemForm', $config_schema);
$output['#title'] = $this
->t('Raw configuration data for %name', [
'%name' => $name,
]);
return $output;
}
public function getRawData($name) {
$data = $this->configInspectorManager
->getConfigData($name);
$output = [
'#title' => $this
->t('Raw configuration data for %name', [
'%name' => $name,
]),
'config' => $this
->formatData($data, 'Configuration data'),
'schema' => $this
->formatData(NULL, 'Configuration schema'),
'validation' => $this
->formatData(TRUE, 'Configuration validation'),
];
if ($this->configInspectorManager
->hasSchema($name)) {
$definition = $this->configInspectorManager
->getDefinition($name);
$output['schema'] = $this
->formatData($definition, 'Configuration schema');
$result = $this->configInspectorManager
->checkValues($name);
if (is_array($result)) {
$output['validation'] = $this
->formatData($result, 'Configuration validation');
}
}
return $output;
}
public function download($name) {
$data = $this->configInspectorManager
->getConfigData($name);
$data = Yaml::encode($data);
$headers = [
'Content-disposition' => 'attachment; filename="' . $name . '.yml"',
];
return new Response($data, 200, $headers);
}
protected function formatList($config_name, $config_schema) {
$rows = [];
$errors = (array) $this->configInspectorManager
->checkValues($config_name);
$schema = $this->configInspectorManager
->convertConfigElementToList($config_schema);
foreach ($schema as $key => $element) {
$definition = $element
->getDataDefinition();
$rows[] = [
'class' => isset($errors[$config_name . ':' . $key]) ? [
'config-inspector-error',
] : [],
'data' => [
[
'class' => [
'icon',
],
'data' => '',
],
$key,
$definition['label'],
$definition['type'],
$this
->formatValue($element),
@$errors[$config_name . ':' . $key] ?: '',
],
];
}
return [
'#attached' => [
'library' => [
'config_inspector/config_inspector',
],
],
'#type' => 'table',
'#header' => [
'',
$this
->t('Name'),
$this
->t('Label'),
$this
->t('Type'),
$this
->t('Value'),
$this
->t('Error'),
],
'#rows' => $rows,
];
}
public function formatTree($schema, $collapsed = FALSE, $base_key = '') {
$build = [];
foreach ($schema as $key => $element) {
$definition = $element
->getDataDefinition();
$label = $definition['label'] ?: $this
->t('N/A');
$type = $definition['type'];
$element_key = $base_key . $key;
if ($element instanceof ArrayElement) {
$build[$key] = [
'#type' => 'details',
'#title' => $label,
'#description' => $element_key . ' (' . $type . ')',
'#description_display' => 'after',
'#open' => !$collapsed,
] + $this
->formatTree($element, TRUE, $element_key . '.');
}
else {
$build[$key] = [
'#type' => 'item',
'#title' => $label,
'#plain_text' => $this
->formatValue($element),
'#description' => $element_key . ' (' . $type . ')',
'#description_display' => 'after',
];
}
}
return $build;
}
protected function formatValue(TypedDataInterface $element) {
$value = $element
->getValue();
if (is_bool($value)) {
return $value ? 'true' : 'false';
}
if (is_scalar($value)) {
return $value;
}
if (empty($value)) {
return '<' . $this
->t('empty') . '>';
}
return '<' . gettype($value) . '>';
}
protected function formatData($data, $title = 'Data') {
if ($this->dumper && $this->moduleHandler
->moduleExists('devel')) {
$output = $this->dumper
->export($data, $title);
}
else {
$output = '<h2>' . $title . '</h2>';
$output .= '<pre>';
$output .= htmlspecialchars(var_export($data, TRUE));
$output .= '</pre>';
$output .= '<br />';
}
return [
'#markup' => $output,
];
}
}