Move all files to 2017/
This commit is contained in:
parent
ac7370f67f
commit
2875863330
15717 changed files with 0 additions and 0 deletions
7
2017/web/core/modules/config/config.info.yml
Normal file
7
2017/web/core/modules/config/config.info.yml
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
name: 'Configuration Manager'
|
||||
type: module
|
||||
description: 'Allows administrators to manage configuration changes.'
|
||||
package: Core
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
configure: config.sync
|
||||
5
2017/web/core/modules/config/config.links.menu.yml
Normal file
5
2017/web/core/modules/config/config.links.menu.yml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
config.sync:
|
||||
title: 'Configuration synchronization'
|
||||
description: 'Import and export your configuration.'
|
||||
route_name: config.sync
|
||||
parent: system.admin_config_development
|
||||
34
2017/web/core/modules/config/config.links.task.yml
Normal file
34
2017/web/core/modules/config/config.links.task.yml
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
config.sync:
|
||||
route_name: config.sync
|
||||
base_route: config.sync
|
||||
title: 'Synchronize'
|
||||
|
||||
config.import:
|
||||
route_name: config.import_full
|
||||
title: 'Import'
|
||||
base_route: config.sync
|
||||
|
||||
config.export:
|
||||
route_name: config.export_full
|
||||
title: 'Export'
|
||||
base_route: config.sync
|
||||
|
||||
config.export_full:
|
||||
route_name: config.export_full
|
||||
title: Full archive
|
||||
parent_id: config.export
|
||||
|
||||
config.import_full:
|
||||
route_name: config.import_full
|
||||
title: Full archive
|
||||
parent_id: config.import
|
||||
|
||||
config.export_single:
|
||||
route_name: config.export_single
|
||||
title: Single item
|
||||
parent_id: config.export
|
||||
|
||||
config.import_single:
|
||||
route_name: config.import_single
|
||||
title: Single item
|
||||
parent_id: config.import
|
||||
81
2017/web/core/modules/config/config.module
Normal file
81
2017/web/core/modules/config/config.module
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Allows site administrators to modify configuration.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
|
||||
/**
|
||||
* Implements hook_help().
|
||||
*/
|
||||
function config_help($route_name, RouteMatchInterface $route_match) {
|
||||
switch ($route_name) {
|
||||
case 'help.page.config':
|
||||
$output = '';
|
||||
$output .= '<h3>' . t('About') . '</h3>';
|
||||
$output .= '<p>' . t('The Configuration Manager module provides a user interface for importing and exporting configuration changes between installations of your website in different environments. Configuration is stored in YAML format. For more information, see the <a href=":url">online documentation for the Configuration Manager module</a>.', [':url' => 'https://www.drupal.org/documentation/administer/config']) . '</p>';
|
||||
$output .= '<h3>' . t('Uses') . '</h3>';
|
||||
$output .= '<dl>';
|
||||
$output .= '<dt>' . t('Exporting the full configuration') . '</dt>';
|
||||
$output .= '<dd>' . t('You can create and download an archive consisting of all your site\'s configuration exported as <em>*.yml</em> files on the <a href=":url">Export</a> page.', [':url' => \Drupal::url('config.export_full')]) . '</dd>';
|
||||
$output .= '<dt>' . t('Importing a full configuration') . '</dt>';
|
||||
$output .= '<dd>' . t('You can upload a full site configuration from an archive file on the <a href=":url">Import</a> page. When importing data from a different environment, the site and import files must have matching configuration values for UUID in the <em>system.site</em> configuration item. That means that your other environments should initially be set up as clones of the target site. Migrations are not supported.', [':url' => \Drupal::url('config.import_full')]) . '</dd>';
|
||||
$output .= '<dt>' . t('Synchronizing configuration') . '</dt>';
|
||||
$output .= '<dd>' . t('You can review differences between the active configuration and an imported configuration archive on the <a href=":synchronize">Synchronize</a> page to ensure that the changes are as expected, before finalizing the import. The Synchronize page also shows configuration items that would be added or removed.', [':synchronize' => \Drupal::url('config.sync')]) . '</dd>';
|
||||
$output .= '<dt>' . t('Exporting a single configuration item') . '</dt>';
|
||||
$output .= '<dd>' . t('You can export a single configuration item by selecting a <em>Configuration type</em> and <em>Configuration name</em> on the <a href=":single-export">Single export</a> page. The configuration and its corresponding <em>*.yml file name</em> are then displayed on the page for you to copy.', [':single-export' => \Drupal::url('config.export_single')]) . '</dd>';
|
||||
$output .= '<dt>' . t('Importing a single configuration item') . '</dt>';
|
||||
$output .= '<dd>' . t('You can import a single configuration item by pasting it in YAML format into the form on the <a href=":single-import">Single import</a> page.', [':single-import' => \Drupal::url('config.import_single')]) . '</dd>';
|
||||
$output .= '</dl>';
|
||||
return $output;
|
||||
|
||||
case 'config.sync':
|
||||
$output = '';
|
||||
$output .= '<p>' . t('Compare the configuration uploaded to your sync directory with the active configuration before completing the import.') . '</p>';
|
||||
return $output;
|
||||
|
||||
case 'config.export_full':
|
||||
$output = '';
|
||||
$output .= '<p>' . t('Export and download the full configuration of this site as a gzipped tar file.') . '</p>';
|
||||
return $output;
|
||||
|
||||
case 'config.import_full':
|
||||
$output = '';
|
||||
$output .= '<p>' . t('Upload a full site configuration archive to the sync directory. It can then be compared and imported on the Synchronize page.') . '</p>';
|
||||
return $output;
|
||||
|
||||
case 'config.export_single':
|
||||
$output = '';
|
||||
$output .= '<p>' . t('Choose a configuration item to display its YAML structure.') . '</p>';
|
||||
return $output;
|
||||
|
||||
case 'config.import_single':
|
||||
$output = '';
|
||||
$output .= '<p>' . t('Import a single configuration item by pasting its YAML structure into the text field.') . '</p>';
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_file_download().
|
||||
*/
|
||||
function config_file_download($uri) {
|
||||
$scheme = file_uri_scheme($uri);
|
||||
$target = file_uri_target($uri);
|
||||
if ($scheme == 'temporary' && $target == 'config.tar.gz') {
|
||||
if (\Drupal::currentUser()->hasPermission('export configuration')) {
|
||||
$request = \Drupal::request();
|
||||
$date = DateTime::createFromFormat('U', $request->server->get('REQUEST_TIME'));
|
||||
$date_string = $date->format('Y-m-d-H-i');
|
||||
$hostname = str_replace('.', '-', $request->getHttpHost());
|
||||
$filename = 'config' . '-' . $hostname . '-' . $date_string . '.tar.gz';
|
||||
$disposition = 'attachment; filename="' . $filename . '"';
|
||||
return [
|
||||
'Content-disposition' => $disposition,
|
||||
];
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
9
2017/web/core/modules/config/config.permissions.yml
Normal file
9
2017/web/core/modules/config/config.permissions.yml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
synchronize configuration:
|
||||
title: 'Synchronize configuration'
|
||||
restrict access: true
|
||||
export configuration:
|
||||
title: 'Export configuration'
|
||||
restrict access: true
|
||||
import configuration:
|
||||
title: 'Import configuration'
|
||||
restrict access: true
|
||||
64
2017/web/core/modules/config/config.routing.yml
Normal file
64
2017/web/core/modules/config/config.routing.yml
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
config.sync:
|
||||
path: '/admin/config/development/configuration'
|
||||
defaults:
|
||||
_form: '\Drupal\config\Form\ConfigSync'
|
||||
_title: 'Synchronize'
|
||||
requirements:
|
||||
_permission: 'synchronize configuration'
|
||||
|
||||
config.diff:
|
||||
path: '/admin/config/development/configuration/sync/diff/{source_name}/{target_name}'
|
||||
defaults:
|
||||
_controller: '\Drupal\config\Controller\ConfigController::diff'
|
||||
target_name: NULL
|
||||
requirements:
|
||||
_permission: 'synchronize configuration'
|
||||
|
||||
config.diff_collection:
|
||||
path: '/admin/config/development/configuration/sync/diff_collection/{collection}/{source_name}/{target_name}'
|
||||
defaults:
|
||||
_controller: '\Drupal\config\Controller\ConfigController::diff'
|
||||
target_name: NULL
|
||||
requirements:
|
||||
_permission: 'synchronize configuration'
|
||||
|
||||
config.export_download:
|
||||
path: '/admin/config/development/configuration/full/export-download'
|
||||
defaults:
|
||||
_controller: '\Drupal\config\Controller\ConfigController::downloadExport'
|
||||
requirements:
|
||||
_permission: 'export configuration'
|
||||
|
||||
config.export_full:
|
||||
path: '/admin/config/development/configuration/full/export'
|
||||
defaults:
|
||||
_form: '\Drupal\config\Form\ConfigExportForm'
|
||||
_title: 'Export'
|
||||
requirements:
|
||||
_permission: 'export configuration'
|
||||
|
||||
config.import_full:
|
||||
path: '/admin/config/development/configuration/full/import'
|
||||
defaults:
|
||||
_form: '\Drupal\config\Form\ConfigImportForm'
|
||||
_title: 'Import'
|
||||
requirements:
|
||||
_permission: 'import configuration'
|
||||
|
||||
config.import_single:
|
||||
path: '/admin/config/development/configuration/single/import'
|
||||
defaults:
|
||||
_title: 'Single import'
|
||||
_form: '\Drupal\config\Form\ConfigSingleImportForm'
|
||||
requirements:
|
||||
_permission: 'import configuration'
|
||||
|
||||
config.export_single:
|
||||
path: '/admin/config/development/configuration/single/export/{config_type}/{config_name}'
|
||||
defaults:
|
||||
_title: 'Single export'
|
||||
_form: '\Drupal\config\Form\ConfigSingleExportForm'
|
||||
config_type: NULL
|
||||
config_name: NULL
|
||||
requirements:
|
||||
_permission: 'export configuration'
|
||||
5
2017/web/core/modules/config/config.services.yml
Normal file
5
2017/web/core/modules/config/config.services.yml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
services:
|
||||
config.config_subscriber:
|
||||
class: Drupal\config\ConfigSubscriber
|
||||
tags:
|
||||
- { name: event_subscriber }
|
||||
41
2017/web/core/modules/config/src/ConfigSubscriber.php
Normal file
41
2017/web/core/modules/config/src/ConfigSubscriber.php
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\config;
|
||||
|
||||
use Drupal\Core\Config\ConfigEvents;
|
||||
use Drupal\Core\Config\ConfigImporterEvent;
|
||||
use Drupal\Core\Config\ConfigImportValidateEventSubscriberBase;
|
||||
|
||||
/**
|
||||
* Config subscriber.
|
||||
*/
|
||||
class ConfigSubscriber extends ConfigImportValidateEventSubscriberBase {
|
||||
|
||||
/**
|
||||
* Checks that the Configuration module is not being uninstalled.
|
||||
*
|
||||
* @param \Drupal\Core\Config\ConfigImporterEvent $event
|
||||
* The config import event.
|
||||
*/
|
||||
public function onConfigImporterValidate(ConfigImporterEvent $event) {
|
||||
// Make sure config syncs performed via the Config UI don't break, but
|
||||
// don't worry about syncs initiated via the command line.
|
||||
if (PHP_SAPI === 'cli') {
|
||||
return;
|
||||
}
|
||||
$importer = $event->getConfigImporter();
|
||||
$core_extension = $importer->getStorageComparer()->getSourceStorage()->read('core.extension');
|
||||
if (!isset($core_extension['module']['config'])) {
|
||||
$importer->logError($this->t('Can not uninstall the Configuration module as part of a configuration synchronization through the user interface.'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents() {
|
||||
$events[ConfigEvents::IMPORT_VALIDATE][] = ['onConfigImporterValidate', 20];
|
||||
return $events;
|
||||
}
|
||||
|
||||
}
|
||||
164
2017/web/core/modules/config/src/Controller/ConfigController.php
Normal file
164
2017/web/core/modules/config/src/Controller/ConfigController.php
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\config\Controller;
|
||||
|
||||
use Drupal\Core\Archiver\ArchiveTar;
|
||||
use Drupal\Core\Config\ConfigManagerInterface;
|
||||
use Drupal\Core\Config\StorageInterface;
|
||||
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
|
||||
use Drupal\Core\Diff\DiffFormatter;
|
||||
use Drupal\Core\Serialization\Yaml;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\system\FileDownloadController;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Returns responses for config module routes.
|
||||
*/
|
||||
class ConfigController implements ContainerInjectionInterface {
|
||||
|
||||
/**
|
||||
* The target storage.
|
||||
*
|
||||
* @var \Drupal\Core\Config\StorageInterface
|
||||
*/
|
||||
protected $targetStorage;
|
||||
|
||||
/**
|
||||
* The source storage.
|
||||
*
|
||||
* @var \Drupal\Core\Config\StorageInterface
|
||||
*/
|
||||
protected $sourceStorage;
|
||||
|
||||
/**
|
||||
* The configuration manager.
|
||||
*
|
||||
* @var \Drupal\Core\Config\ConfigManagerInterface
|
||||
*/
|
||||
protected $configManager;
|
||||
|
||||
/**
|
||||
* The file download controller.
|
||||
*
|
||||
* @var \Drupal\system\FileDownloadController
|
||||
*/
|
||||
protected $fileDownloadController;
|
||||
|
||||
/**
|
||||
* The diff formatter.
|
||||
*
|
||||
* @var \Drupal\Core\Diff\DiffFormatter
|
||||
*/
|
||||
protected $diffFormatter;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('config.storage'),
|
||||
$container->get('config.storage.sync'),
|
||||
$container->get('config.manager'),
|
||||
new FileDownloadController(),
|
||||
$container->get('diff.formatter')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a ConfigController object.
|
||||
*
|
||||
* @param \Drupal\Core\Config\StorageInterface $target_storage
|
||||
* The target storage.
|
||||
* @param \Drupal\Core\Config\StorageInterface $source_storage
|
||||
* The source storage
|
||||
* @param \Drupal\system\FileDownloadController $file_download_controller
|
||||
* The file download controller.
|
||||
*/
|
||||
public function __construct(StorageInterface $target_storage, StorageInterface $source_storage, ConfigManagerInterface $config_manager, FileDownloadController $file_download_controller, DiffFormatter $diff_formatter) {
|
||||
$this->targetStorage = $target_storage;
|
||||
$this->sourceStorage = $source_storage;
|
||||
$this->configManager = $config_manager;
|
||||
$this->fileDownloadController = $file_download_controller;
|
||||
$this->diffFormatter = $diff_formatter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads a tarball of the site configuration.
|
||||
*/
|
||||
public function downloadExport() {
|
||||
file_unmanaged_delete(file_directory_temp() . '/config.tar.gz');
|
||||
|
||||
$archiver = new ArchiveTar(file_directory_temp() . '/config.tar.gz', 'gz');
|
||||
// Get raw configuration data without overrides.
|
||||
foreach ($this->configManager->getConfigFactory()->listAll() as $name) {
|
||||
$archiver->addString("$name.yml", Yaml::encode($this->configManager->getConfigFactory()->get($name)->getRawData()));
|
||||
}
|
||||
// Get all override data from the remaining collections.
|
||||
foreach ($this->targetStorage->getAllCollectionNames() as $collection) {
|
||||
$collection_storage = $this->targetStorage->createCollection($collection);
|
||||
foreach ($collection_storage->listAll() as $name) {
|
||||
$archiver->addString(str_replace('.', '/', $collection) . "/$name.yml", Yaml::encode($collection_storage->read($name)));
|
||||
}
|
||||
}
|
||||
|
||||
$request = new Request(['file' => 'config.tar.gz']);
|
||||
return $this->fileDownloadController->download($request, 'temporary');
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows diff of specified configuration file.
|
||||
*
|
||||
* @param string $source_name
|
||||
* The name of the configuration file.
|
||||
* @param string $target_name
|
||||
* (optional) The name of the target configuration file if different from
|
||||
* the $source_name.
|
||||
* @param string $collection
|
||||
* (optional) The configuration collection name. Defaults to the default
|
||||
* collection.
|
||||
*
|
||||
* @return string
|
||||
* Table showing a two-way diff between the active and staged configuration.
|
||||
*/
|
||||
public function diff($source_name, $target_name = NULL, $collection = NULL) {
|
||||
if (!isset($collection)) {
|
||||
$collection = StorageInterface::DEFAULT_COLLECTION;
|
||||
}
|
||||
$diff = $this->configManager->diff($this->targetStorage, $this->sourceStorage, $source_name, $target_name, $collection);
|
||||
$this->diffFormatter->show_header = FALSE;
|
||||
|
||||
$build = [];
|
||||
|
||||
$build['#title'] = t('View changes of @config_file', ['@config_file' => $source_name]);
|
||||
// Add the CSS for the inline diff.
|
||||
$build['#attached']['library'][] = 'system/diff';
|
||||
|
||||
$build['diff'] = [
|
||||
'#type' => 'table',
|
||||
'#attributes' => [
|
||||
'class' => ['diff'],
|
||||
],
|
||||
'#header' => [
|
||||
['data' => t('Active'), 'colspan' => '2'],
|
||||
['data' => t('Staged'), 'colspan' => '2'],
|
||||
],
|
||||
'#rows' => $this->diffFormatter->format($diff),
|
||||
];
|
||||
|
||||
$build['back'] = [
|
||||
'#type' => 'link',
|
||||
'#attributes' => [
|
||||
'class' => [
|
||||
'dialog-cancel',
|
||||
],
|
||||
],
|
||||
'#title' => "Back to 'Synchronize configuration' page.",
|
||||
'#url' => Url::fromRoute('config.sync'),
|
||||
];
|
||||
|
||||
return $build;
|
||||
}
|
||||
|
||||
}
|
||||
40
2017/web/core/modules/config/src/Form/ConfigExportForm.php
Normal file
40
2017/web/core/modules/config/src/Form/ConfigExportForm.php
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\config\Form;
|
||||
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* Defines the configuration export form.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class ConfigExportForm extends FormBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'config_export_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$form['submit'] = [
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('Export'),
|
||||
];
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$form_state->setRedirect('config.export_download');
|
||||
}
|
||||
|
||||
}
|
||||
113
2017/web/core/modules/config/src/Form/ConfigImportForm.php
Normal file
113
2017/web/core/modules/config/src/Form/ConfigImportForm.php
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\config\Form;
|
||||
|
||||
use Drupal\Core\Archiver\ArchiveTar;
|
||||
use Drupal\Core\Config\StorageInterface;
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Defines the configuration import form.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class ConfigImportForm extends FormBase {
|
||||
|
||||
/**
|
||||
* The configuration storage.
|
||||
*
|
||||
* @var \Drupal\Core\Config\StorageInterface
|
||||
*/
|
||||
protected $configStorage;
|
||||
|
||||
/**
|
||||
* Constructs a new ConfigImportForm.
|
||||
*
|
||||
* @param \Drupal\Core\Config\StorageInterface $config_storage
|
||||
* The configuration storage.
|
||||
*/
|
||||
public function __construct(StorageInterface $config_storage) {
|
||||
$this->configStorage = $config_storage;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('config.storage.sync')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'config_import_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$directory = config_get_config_directory(CONFIG_SYNC_DIRECTORY);
|
||||
$directory_is_writable = is_writable($directory);
|
||||
if (!$directory_is_writable) {
|
||||
$this->messenger()->addError($this->t('The directory %directory is not writable.', ['%directory' => $directory]));
|
||||
}
|
||||
$form['import_tarball'] = [
|
||||
'#type' => 'file',
|
||||
'#title' => $this->t('Configuration archive'),
|
||||
'#description' => $this->t('Allowed types: @extensions.', ['@extensions' => 'tar.gz tgz tar.bz2']),
|
||||
];
|
||||
|
||||
$form['submit'] = [
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('Upload'),
|
||||
'#disabled' => !$directory_is_writable,
|
||||
];
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateForm(array &$form, FormStateInterface $form_state) {
|
||||
$all_files = $this->getRequest()->files->get('files', []);
|
||||
if (!empty($all_files['import_tarball'])) {
|
||||
$file_upload = $all_files['import_tarball'];
|
||||
if ($file_upload->isValid()) {
|
||||
$form_state->setValue('import_tarball', $file_upload->getRealPath());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$form_state->setErrorByName('import_tarball', $this->t('The file could not be uploaded.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
if ($path = $form_state->getValue('import_tarball')) {
|
||||
$this->configStorage->deleteAll();
|
||||
try {
|
||||
$archiver = new ArchiveTar($path, 'gz');
|
||||
$files = [];
|
||||
foreach ($archiver->listContent() as $file) {
|
||||
$files[] = $file['filename'];
|
||||
}
|
||||
$archiver->extractList($files, config_get_config_directory(CONFIG_SYNC_DIRECTORY));
|
||||
$this->messenger()->addStatus($this->t('Your configuration files were successfully uploaded and are ready for import.'));
|
||||
$form_state->setRedirect('config.sync');
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
$this->messenger()->addError($this->t('Could not extract the contents of the tar file. The error message is <em>@message</em>', ['@message' => $e->getMessage()]));
|
||||
}
|
||||
drupal_unlink($path);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
207
2017/web/core/modules/config/src/Form/ConfigSingleExportForm.php
Normal file
207
2017/web/core/modules/config/src/Form/ConfigSingleExportForm.php
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\config\Form;
|
||||
|
||||
use Drupal\Core\Config\Entity\ConfigEntityInterface;
|
||||
use Drupal\Core\Config\StorageInterface;
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormState;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Serialization\Yaml;
|
||||
use Drupal\Core\StringTranslation\TranslatableMarkup;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Provides a form for exporting a single configuration file.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class ConfigSingleExportForm extends FormBase {
|
||||
|
||||
/**
|
||||
* The entity manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityManagerInterface
|
||||
*/
|
||||
protected $entityManager;
|
||||
|
||||
/**
|
||||
* The config storage.
|
||||
*
|
||||
* @var \Drupal\Core\Config\StorageInterface
|
||||
*/
|
||||
protected $configStorage;
|
||||
|
||||
/**
|
||||
* Tracks the valid config entity type definitions.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeInterface[]
|
||||
*/
|
||||
protected $definitions = [];
|
||||
|
||||
/**
|
||||
* Constructs a new ConfigSingleImportForm.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
||||
* The entity manager.
|
||||
* @param \Drupal\Core\Config\StorageInterface $config_storage
|
||||
* The config storage.
|
||||
*/
|
||||
public function __construct(EntityManagerInterface $entity_manager, StorageInterface $config_storage) {
|
||||
$this->entityManager = $entity_manager;
|
||||
$this->configStorage = $config_storage;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('entity.manager'),
|
||||
$container->get('config.storage')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'config_single_export_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state, $config_type = NULL, $config_name = NULL) {
|
||||
foreach ($this->entityManager->getDefinitions() as $entity_type => $definition) {
|
||||
if ($definition->entityClassImplements(ConfigEntityInterface::class)) {
|
||||
$this->definitions[$entity_type] = $definition;
|
||||
}
|
||||
}
|
||||
$entity_types = array_map(function (EntityTypeInterface $definition) {
|
||||
return $definition->getLabel();
|
||||
}, $this->definitions);
|
||||
// Sort the entity types by label, then add the simple config to the top.
|
||||
uasort($entity_types, 'strnatcasecmp');
|
||||
$config_types = [
|
||||
'system.simple' => $this->t('Simple configuration'),
|
||||
] + $entity_types;
|
||||
$form['config_type'] = [
|
||||
'#title' => $this->t('Configuration type'),
|
||||
'#type' => 'select',
|
||||
'#options' => $config_types,
|
||||
'#default_value' => $config_type,
|
||||
'#ajax' => [
|
||||
'callback' => '::updateConfigurationType',
|
||||
'wrapper' => 'edit-config-type-wrapper',
|
||||
],
|
||||
];
|
||||
$default_type = $form_state->getValue('config_type', $config_type);
|
||||
$form['config_name'] = [
|
||||
'#title' => $this->t('Configuration name'),
|
||||
'#type' => 'select',
|
||||
'#options' => $this->findConfiguration($default_type),
|
||||
'#default_value' => $config_name,
|
||||
'#prefix' => '<div id="edit-config-type-wrapper">',
|
||||
'#suffix' => '</div>',
|
||||
'#ajax' => [
|
||||
'callback' => '::updateExport',
|
||||
'wrapper' => 'edit-export-wrapper',
|
||||
],
|
||||
];
|
||||
|
||||
$form['export'] = [
|
||||
'#title' => $this->t('Here is your configuration:'),
|
||||
'#type' => 'textarea',
|
||||
'#rows' => 24,
|
||||
'#prefix' => '<div id="edit-export-wrapper">',
|
||||
'#suffix' => '</div>',
|
||||
];
|
||||
if ($config_type && $config_name) {
|
||||
$fake_form_state = (new FormState())->setValues([
|
||||
'config_type' => $config_type,
|
||||
'config_name' => $config_name,
|
||||
]);
|
||||
$form['export'] = $this->updateExport($form, $fake_form_state);
|
||||
}
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles switching the configuration type selector.
|
||||
*/
|
||||
public function updateConfigurationType($form, FormStateInterface $form_state) {
|
||||
$form['config_name']['#options'] = $this->findConfiguration($form_state->getValue('config_type'));
|
||||
return $form['config_name'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles switching the export textarea.
|
||||
*/
|
||||
public function updateExport($form, FormStateInterface $form_state) {
|
||||
// Determine the full config name for the selected config entity.
|
||||
if ($form_state->getValue('config_type') !== 'system.simple') {
|
||||
$definition = $this->entityManager->getDefinition($form_state->getValue('config_type'));
|
||||
$name = $definition->getConfigPrefix() . '.' . $form_state->getValue('config_name');
|
||||
}
|
||||
// The config name is used directly for simple configuration.
|
||||
else {
|
||||
$name = $form_state->getValue('config_name');
|
||||
}
|
||||
// Read the raw data for this config name, encode it, and display it.
|
||||
$form['export']['#value'] = Yaml::encode($this->configStorage->read($name));
|
||||
$form['export']['#description'] = $this->t('Filename: %name', ['%name' => $name . '.yml']);
|
||||
return $form['export'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles switching the configuration type selector.
|
||||
*/
|
||||
protected function findConfiguration($config_type) {
|
||||
$names = [
|
||||
'' => $this->t('- Select -'),
|
||||
];
|
||||
// For a given entity type, load all entities.
|
||||
if ($config_type && $config_type !== 'system.simple') {
|
||||
$entity_storage = $this->entityManager->getStorage($config_type);
|
||||
foreach ($entity_storage->loadMultiple() as $entity) {
|
||||
$entity_id = $entity->id();
|
||||
if ($label = $entity->label()) {
|
||||
$names[$entity_id] = new TranslatableMarkup('@label (@id)', ['@label' => $label, '@id' => $entity_id]);
|
||||
}
|
||||
else {
|
||||
$names[$entity_id] = $entity_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Handle simple configuration.
|
||||
else {
|
||||
// Gather the config entity prefixes.
|
||||
$config_prefixes = array_map(function (EntityTypeInterface $definition) {
|
||||
return $definition->getConfigPrefix() . '.';
|
||||
}, $this->definitions);
|
||||
|
||||
// Find all config, and then filter our anything matching a config prefix.
|
||||
$names = $this->configStorage->listAll();
|
||||
$names = array_combine($names, $names);
|
||||
foreach ($names as $config_name) {
|
||||
foreach ($config_prefixes as $config_prefix) {
|
||||
if (strpos($config_name, $config_prefix) === 0) {
|
||||
unset($names[$config_name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $names;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
// Nothing to submit.
|
||||
}
|
||||
|
||||
}
|
||||
427
2017/web/core/modules/config/src/Form/ConfigSingleImportForm.php
Normal file
427
2017/web/core/modules/config/src/Form/ConfigSingleImportForm.php
Normal file
|
|
@ -0,0 +1,427 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\config\Form;
|
||||
|
||||
use Drupal\Component\Serialization\Exception\InvalidDataTypeException;
|
||||
use Drupal\config\StorageReplaceDataWrapper;
|
||||
use Drupal\Core\Config\ConfigImporter;
|
||||
use Drupal\Core\Config\ConfigImporterException;
|
||||
use Drupal\Core\Config\ConfigManagerInterface;
|
||||
use Drupal\Core\Config\Entity\ConfigEntityInterface;
|
||||
use Drupal\Core\Config\StorageComparer;
|
||||
use Drupal\Core\Config\StorageInterface;
|
||||
use Drupal\Core\Config\TypedConfigManagerInterface;
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Extension\ModuleInstallerInterface;
|
||||
use Drupal\Core\Extension\ThemeHandlerInterface;
|
||||
use Drupal\Core\Form\ConfirmFormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Lock\LockBackendInterface;
|
||||
use Drupal\Core\Render\RendererInterface;
|
||||
use Drupal\Core\Serialization\Yaml;
|
||||
use Drupal\Core\Url;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
/**
|
||||
* Provides a form for importing a single configuration file.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class ConfigSingleImportForm extends ConfirmFormBase {
|
||||
|
||||
/**
|
||||
* The entity manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityManagerInterface
|
||||
*/
|
||||
protected $entityManager;
|
||||
|
||||
/**
|
||||
* The config storage.
|
||||
*
|
||||
* @var \Drupal\Core\Config\StorageInterface
|
||||
*/
|
||||
protected $configStorage;
|
||||
|
||||
/**
|
||||
* The renderer service.
|
||||
*
|
||||
* @var \Drupal\Core\Render\RendererInterface
|
||||
*/
|
||||
protected $renderer;
|
||||
|
||||
/**
|
||||
* The event dispatcher.
|
||||
*
|
||||
* @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
|
||||
*/
|
||||
protected $eventDispatcher;
|
||||
|
||||
/**
|
||||
* The configuration manager.
|
||||
*
|
||||
* @var \Drupal\Core\Config\ConfigManagerInterface
|
||||
*/
|
||||
protected $configManager;
|
||||
|
||||
/**
|
||||
* The database lock object.
|
||||
*
|
||||
* @var \Drupal\Core\Lock\LockBackendInterface
|
||||
*/
|
||||
protected $lock;
|
||||
|
||||
/**
|
||||
* The typed config manager.
|
||||
*
|
||||
* @var \Drupal\Core\Config\TypedConfigManagerInterface
|
||||
*/
|
||||
protected $typedConfigManager;
|
||||
|
||||
/**
|
||||
* The module handler.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ModuleHandlerInterface
|
||||
*/
|
||||
protected $moduleHandler;
|
||||
|
||||
/**
|
||||
* The theme handler.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ThemeHandlerInterface
|
||||
*/
|
||||
protected $themeHandler;
|
||||
|
||||
/**
|
||||
* The module installer.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ModuleInstallerInterface
|
||||
*/
|
||||
protected $moduleInstaller;
|
||||
|
||||
/**
|
||||
* If the config exists, this is that object. Otherwise, FALSE.
|
||||
*
|
||||
* @var \Drupal\Core\Config\Config|\Drupal\Core\Config\Entity\ConfigEntityInterface|bool
|
||||
*/
|
||||
protected $configExists = FALSE;
|
||||
|
||||
/**
|
||||
* The submitted data needing to be confirmed.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $data = [];
|
||||
|
||||
/**
|
||||
* Constructs a new ConfigSingleImportForm.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
||||
* The entity manager.
|
||||
* @param \Drupal\Core\Config\StorageInterface $config_storage
|
||||
* The config storage.
|
||||
* @param \Drupal\Core\Render\RendererInterface $renderer
|
||||
* The renderer service.
|
||||
* @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
|
||||
* The event dispatcher used to notify subscribers of config import events.
|
||||
* @param \Drupal\Core\Config\ConfigManagerInterface $config_manager
|
||||
* The configuration manager.
|
||||
* @param \Drupal\Core\Lock\LockBackendInterface $lock
|
||||
* The lock backend to ensure multiple imports do not occur at the same time.
|
||||
* @param \Drupal\Core\Config\TypedConfigManagerInterface $typed_config
|
||||
* The typed configuration manager.
|
||||
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
|
||||
* The module handler.
|
||||
* @param \Drupal\Core\Extension\ModuleInstallerInterface $module_installer
|
||||
* The module installer.
|
||||
* @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
|
||||
* The theme handler.
|
||||
*/
|
||||
public function __construct(EntityManagerInterface $entity_manager, StorageInterface $config_storage, RendererInterface $renderer, EventDispatcherInterface $event_dispatcher, ConfigManagerInterface $config_manager, LockBackendInterface $lock, TypedConfigManagerInterface $typed_config, ModuleHandlerInterface $module_handler, ModuleInstallerInterface $module_installer, ThemeHandlerInterface $theme_handler) {
|
||||
$this->entityManager = $entity_manager;
|
||||
$this->configStorage = $config_storage;
|
||||
$this->renderer = $renderer;
|
||||
|
||||
// Services necessary for \Drupal\Core\Config\ConfigImporter.
|
||||
$this->eventDispatcher = $event_dispatcher;
|
||||
$this->configManager = $config_manager;
|
||||
$this->lock = $lock;
|
||||
$this->typedConfigManager = $typed_config;
|
||||
$this->moduleHandler = $module_handler;
|
||||
$this->moduleInstaller = $module_installer;
|
||||
$this->themeHandler = $theme_handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('entity.manager'),
|
||||
$container->get('config.storage'),
|
||||
$container->get('renderer'),
|
||||
$container->get('event_dispatcher'),
|
||||
$container->get('config.manager'),
|
||||
$container->get('lock.persistent'),
|
||||
$container->get('config.typed'),
|
||||
$container->get('module_handler'),
|
||||
$container->get('module_installer'),
|
||||
$container->get('theme_handler')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'config_single_import_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCancelUrl() {
|
||||
return new Url('config.import_single');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getQuestion() {
|
||||
if ($this->data['config_type'] === 'system.simple') {
|
||||
$name = $this->data['config_name'];
|
||||
$type = $this->t('simple configuration');
|
||||
}
|
||||
else {
|
||||
$definition = $this->entityManager->getDefinition($this->data['config_type']);
|
||||
$name = $this->data['import'][$definition->getKey('id')];
|
||||
$type = $definition->getLowercaseLabel();
|
||||
}
|
||||
|
||||
$args = [
|
||||
'%name' => $name,
|
||||
'@type' => strtolower($type),
|
||||
];
|
||||
if ($this->configExists) {
|
||||
$question = $this->t('Are you sure you want to update the %name @type?', $args);
|
||||
}
|
||||
else {
|
||||
$question = $this->t('Are you sure you want to create a new %name @type?', $args);
|
||||
}
|
||||
return $question;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
// When this is the confirmation step fall through to the confirmation form.
|
||||
if ($this->data) {
|
||||
return parent::buildForm($form, $form_state);
|
||||
}
|
||||
|
||||
$entity_types = [];
|
||||
foreach ($this->entityManager->getDefinitions() as $entity_type => $definition) {
|
||||
if ($definition->entityClassImplements(ConfigEntityInterface::class)) {
|
||||
$entity_types[$entity_type] = $definition->getLabel();
|
||||
}
|
||||
}
|
||||
// Sort the entity types by label, then add the simple config to the top.
|
||||
uasort($entity_types, 'strnatcasecmp');
|
||||
$config_types = [
|
||||
'system.simple' => $this->t('Simple configuration'),
|
||||
] + $entity_types;
|
||||
$form['config_type'] = [
|
||||
'#title' => $this->t('Configuration type'),
|
||||
'#type' => 'select',
|
||||
'#options' => $config_types,
|
||||
'#required' => TRUE,
|
||||
];
|
||||
$form['config_name'] = [
|
||||
'#title' => $this->t('Configuration name'),
|
||||
'#description' => $this->t('Enter the name of the configuration file without the <em>.yml</em> extension. (e.g. <em>system.site</em>)'),
|
||||
'#type' => 'textfield',
|
||||
'#states' => [
|
||||
'required' => [
|
||||
':input[name="config_type"]' => ['value' => 'system.simple'],
|
||||
],
|
||||
'visible' => [
|
||||
':input[name="config_type"]' => ['value' => 'system.simple'],
|
||||
],
|
||||
],
|
||||
];
|
||||
$form['import'] = [
|
||||
'#title' => $this->t('Paste your configuration here'),
|
||||
'#type' => 'textarea',
|
||||
'#rows' => 24,
|
||||
'#required' => TRUE,
|
||||
];
|
||||
$form['advanced'] = [
|
||||
'#type' => 'details',
|
||||
'#title' => $this->t('Advanced'),
|
||||
];
|
||||
$form['advanced']['custom_entity_id'] = [
|
||||
'#title' => $this->t('Custom Entity ID'),
|
||||
'#type' => 'textfield',
|
||||
'#description' => $this->t('Specify a custom entity ID. This will override the entity ID in the configuration above.'),
|
||||
];
|
||||
$form['actions'] = ['#type' => 'actions'];
|
||||
$form['actions']['submit'] = [
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('Import'),
|
||||
'#button_type' => 'primary',
|
||||
];
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateForm(array &$form, FormStateInterface $form_state) {
|
||||
// The confirmation step needs no additional validation.
|
||||
if ($this->data) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Decode the submitted import.
|
||||
$data = Yaml::decode($form_state->getValue('import'));
|
||||
}
|
||||
catch (InvalidDataTypeException $e) {
|
||||
$form_state->setErrorByName('import', $this->t('The import failed with the following message: %message', ['%message' => $e->getMessage()]));
|
||||
}
|
||||
|
||||
// Validate for config entities.
|
||||
if ($form_state->getValue('config_type') !== 'system.simple') {
|
||||
$definition = $this->entityManager->getDefinition($form_state->getValue('config_type'));
|
||||
$id_key = $definition->getKey('id');
|
||||
|
||||
// If a custom entity ID is specified, override the value in the
|
||||
// configuration data being imported.
|
||||
if (!$form_state->isValueEmpty('custom_entity_id')) {
|
||||
$data[$id_key] = $form_state->getValue('custom_entity_id');
|
||||
}
|
||||
|
||||
$entity_storage = $this->entityManager->getStorage($form_state->getValue('config_type'));
|
||||
// If an entity ID was not specified, set an error.
|
||||
if (!isset($data[$id_key])) {
|
||||
$form_state->setErrorByName('import', $this->t('Missing ID key "@id_key" for this @entity_type import.', ['@id_key' => $id_key, '@entity_type' => $definition->getLabel()]));
|
||||
return;
|
||||
}
|
||||
|
||||
$config_name = $definition->getConfigPrefix() . '.' . $data[$id_key];
|
||||
// If there is an existing entity, ensure matching ID and UUID.
|
||||
if ($entity = $entity_storage->load($data[$id_key])) {
|
||||
$this->configExists = $entity;
|
||||
if (!isset($data['uuid'])) {
|
||||
$form_state->setErrorByName('import', $this->t('An entity with this machine name already exists but the import did not specify a UUID.'));
|
||||
return;
|
||||
}
|
||||
if ($data['uuid'] !== $entity->uuid()) {
|
||||
$form_state->setErrorByName('import', $this->t('An entity with this machine name already exists but the UUID does not match.'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
// If there is no entity with a matching ID, check for a UUID match.
|
||||
elseif (isset($data['uuid']) && $entity_storage->loadByProperties(['uuid' => $data['uuid']])) {
|
||||
$form_state->setErrorByName('import', $this->t('An entity with this UUID already exists but the machine name does not match.'));
|
||||
}
|
||||
}
|
||||
else {
|
||||
$config_name = $form_state->getValue('config_name');
|
||||
$config = $this->config($config_name);
|
||||
$this->configExists = !$config->isNew() ? $config : FALSE;
|
||||
}
|
||||
|
||||
// Use ConfigImporter validation.
|
||||
if (!$form_state->getErrors()) {
|
||||
$source_storage = new StorageReplaceDataWrapper($this->configStorage);
|
||||
$source_storage->replaceData($config_name, $data);
|
||||
$storage_comparer = new StorageComparer(
|
||||
$source_storage,
|
||||
$this->configStorage,
|
||||
$this->configManager
|
||||
);
|
||||
|
||||
if (!$storage_comparer->createChangelist()->hasChanges()) {
|
||||
$form_state->setErrorByName('import', $this->t('There are no changes to import.'));
|
||||
}
|
||||
else {
|
||||
$config_importer = new ConfigImporter(
|
||||
$storage_comparer,
|
||||
$this->eventDispatcher,
|
||||
$this->configManager,
|
||||
$this->lock,
|
||||
$this->typedConfigManager,
|
||||
$this->moduleHandler,
|
||||
$this->moduleInstaller,
|
||||
$this->themeHandler,
|
||||
$this->getStringTranslation()
|
||||
);
|
||||
|
||||
try {
|
||||
$config_importer->validate();
|
||||
$form_state->set('config_importer', $config_importer);
|
||||
}
|
||||
catch (ConfigImporterException $e) {
|
||||
// There are validation errors.
|
||||
$item_list = [
|
||||
'#theme' => 'item_list',
|
||||
'#items' => $config_importer->getErrors(),
|
||||
'#title' => $this->t('The configuration cannot be imported because it failed validation for the following reasons:'),
|
||||
];
|
||||
$form_state->setErrorByName('import', $this->renderer->render($item_list));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Store the decoded version of the submitted import.
|
||||
$form_state->setValueForElement($form['import'], $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
// If this form has not yet been confirmed, store the values and rebuild.
|
||||
if (!$this->data) {
|
||||
$form_state->setRebuild();
|
||||
$this->data = $form_state->getValues();
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var \Drupal\Core\Config\ConfigImporter $config_importer */
|
||||
$config_importer = $form_state->get('config_importer');
|
||||
if ($config_importer->alreadyImporting()) {
|
||||
$this->messenger()->addError($this->t('Another request may be importing configuration already.'));
|
||||
}
|
||||
else {
|
||||
try {
|
||||
$sync_steps = $config_importer->initialize();
|
||||
$batch = [
|
||||
'operations' => [],
|
||||
'finished' => [ConfigSync::class, 'finishBatch'],
|
||||
'title' => $this->t('Importing configuration'),
|
||||
'init_message' => $this->t('Starting configuration import.'),
|
||||
'progress_message' => $this->t('Completed @current step of @total.'),
|
||||
'error_message' => $this->t('Configuration import has encountered an error.'),
|
||||
];
|
||||
foreach ($sync_steps as $sync_step) {
|
||||
$batch['operations'][] = [[ConfigSync::class, 'processBatch'], [$config_importer, $sync_step]];
|
||||
}
|
||||
|
||||
batch_set($batch);
|
||||
}
|
||||
catch (ConfigImporterException $e) {
|
||||
// There are validation errors.
|
||||
$this->messenger()->addError($this->t('The configuration import failed for the following reasons:'));
|
||||
foreach ($config_importer->getErrors() as $message) {
|
||||
$this->messenger()->addError($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
399
2017/web/core/modules/config/src/Form/ConfigSync.php
Normal file
399
2017/web/core/modules/config/src/Form/ConfigSync.php
Normal file
|
|
@ -0,0 +1,399 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\config\Form;
|
||||
|
||||
use Drupal\Core\Config\ConfigImporterException;
|
||||
use Drupal\Core\Config\ConfigImporter;
|
||||
use Drupal\Core\Config\Importer\ConfigImporterBatch;
|
||||
use Drupal\Core\Config\TypedConfigManagerInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Extension\ModuleInstallerInterface;
|
||||
use Drupal\Core\Extension\ThemeHandlerInterface;
|
||||
use Drupal\Core\Config\ConfigManagerInterface;
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Config\StorageInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Lock\LockBackendInterface;
|
||||
use Drupal\Core\Config\StorageComparer;
|
||||
use Drupal\Core\Render\RendererInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Construct the storage changes in a configuration synchronization form.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class ConfigSync extends FormBase {
|
||||
|
||||
/**
|
||||
* The database lock object.
|
||||
*
|
||||
* @var \Drupal\Core\Lock\LockBackendInterface
|
||||
*/
|
||||
protected $lock;
|
||||
|
||||
/**
|
||||
* The sync configuration object.
|
||||
*
|
||||
* @var \Drupal\Core\Config\StorageInterface
|
||||
*/
|
||||
protected $syncStorage;
|
||||
|
||||
/**
|
||||
* The active configuration object.
|
||||
*
|
||||
* @var \Drupal\Core\Config\StorageInterface
|
||||
*/
|
||||
protected $activeStorage;
|
||||
|
||||
/**
|
||||
* The snapshot configuration object.
|
||||
*
|
||||
* @var \Drupal\Core\Config\StorageInterface
|
||||
*/
|
||||
protected $snapshotStorage;
|
||||
|
||||
/**
|
||||
* Event dispatcher.
|
||||
*
|
||||
* @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
|
||||
*/
|
||||
protected $eventDispatcher;
|
||||
|
||||
/**
|
||||
* The configuration manager.
|
||||
*
|
||||
* @var \Drupal\Core\Config\ConfigManagerInterface
|
||||
*/
|
||||
protected $configManager;
|
||||
|
||||
/**
|
||||
* The typed config manager.
|
||||
*
|
||||
* @var \Drupal\Core\Config\TypedConfigManagerInterface
|
||||
*/
|
||||
protected $typedConfigManager;
|
||||
|
||||
/**
|
||||
* The module handler.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ModuleHandlerInterface
|
||||
*/
|
||||
protected $moduleHandler;
|
||||
|
||||
/**
|
||||
* The theme handler.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ThemeHandlerInterface
|
||||
*/
|
||||
protected $themeHandler;
|
||||
|
||||
/**
|
||||
* The module installer.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ModuleInstallerInterface
|
||||
*/
|
||||
protected $moduleInstaller;
|
||||
|
||||
/**
|
||||
* The renderer.
|
||||
*
|
||||
* @var \Drupal\Core\Render\RendererInterface
|
||||
*/
|
||||
protected $renderer;
|
||||
|
||||
/**
|
||||
* Constructs the object.
|
||||
*
|
||||
* @param \Drupal\Core\Config\StorageInterface $sync_storage
|
||||
* The source storage.
|
||||
* @param \Drupal\Core\Config\StorageInterface $active_storage
|
||||
* The target storage.
|
||||
* @param \Drupal\Core\Config\StorageInterface $snapshot_storage
|
||||
* The snapshot storage.
|
||||
* @param \Drupal\Core\Lock\LockBackendInterface $lock
|
||||
* The lock object.
|
||||
* @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
|
||||
* Event dispatcher.
|
||||
* @param \Drupal\Core\Config\ConfigManagerInterface $config_manager
|
||||
* Configuration manager.
|
||||
* @param \Drupal\Core\Config\TypedConfigManagerInterface $typed_config
|
||||
* The typed configuration manager.
|
||||
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
|
||||
* The module handler.
|
||||
* @param \Drupal\Core\Extension\ModuleInstallerInterface $module_installer
|
||||
* The module installer.
|
||||
* @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
|
||||
* The theme handler.
|
||||
* @param \Drupal\Core\Render\RendererInterface $renderer
|
||||
* The renderer.
|
||||
*/
|
||||
public function __construct(StorageInterface $sync_storage, StorageInterface $active_storage, StorageInterface $snapshot_storage, LockBackendInterface $lock, EventDispatcherInterface $event_dispatcher, ConfigManagerInterface $config_manager, TypedConfigManagerInterface $typed_config, ModuleHandlerInterface $module_handler, ModuleInstallerInterface $module_installer, ThemeHandlerInterface $theme_handler, RendererInterface $renderer) {
|
||||
$this->syncStorage = $sync_storage;
|
||||
$this->activeStorage = $active_storage;
|
||||
$this->snapshotStorage = $snapshot_storage;
|
||||
$this->lock = $lock;
|
||||
$this->eventDispatcher = $event_dispatcher;
|
||||
$this->configManager = $config_manager;
|
||||
$this->typedConfigManager = $typed_config;
|
||||
$this->moduleHandler = $module_handler;
|
||||
$this->moduleInstaller = $module_installer;
|
||||
$this->themeHandler = $theme_handler;
|
||||
$this->renderer = $renderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('config.storage.sync'),
|
||||
$container->get('config.storage'),
|
||||
$container->get('config.storage.snapshot'),
|
||||
$container->get('lock.persistent'),
|
||||
$container->get('event_dispatcher'),
|
||||
$container->get('config.manager'),
|
||||
$container->get('config.typed'),
|
||||
$container->get('module_handler'),
|
||||
$container->get('module_installer'),
|
||||
$container->get('theme_handler'),
|
||||
$container->get('renderer')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'config_admin_import_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$form['actions'] = ['#type' => 'actions'];
|
||||
$form['actions']['submit'] = [
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('Import all'),
|
||||
];
|
||||
$source_list = $this->syncStorage->listAll();
|
||||
$storage_comparer = new StorageComparer($this->syncStorage, $this->activeStorage, $this->configManager);
|
||||
if (empty($source_list) || !$storage_comparer->createChangelist()->hasChanges()) {
|
||||
$form['no_changes'] = [
|
||||
'#type' => 'table',
|
||||
'#header' => [$this->t('Name'), $this->t('Operations')],
|
||||
'#rows' => [],
|
||||
'#empty' => $this->t('There are no configuration changes to import.'),
|
||||
];
|
||||
$form['actions']['#access'] = FALSE;
|
||||
return $form;
|
||||
}
|
||||
elseif (!$storage_comparer->validateSiteUuid()) {
|
||||
$this->messenger()->addError($this->t('The staged configuration cannot be imported, because it originates from a different site than this site. You can only synchronize configuration between cloned instances of this site.'));
|
||||
$form['actions']['#access'] = FALSE;
|
||||
return $form;
|
||||
}
|
||||
// A list of changes will be displayed, so check if the user should be
|
||||
// warned of potential losses to configuration.
|
||||
if ($this->snapshotStorage->exists('core.extension')) {
|
||||
$snapshot_comparer = new StorageComparer($this->activeStorage, $this->snapshotStorage, $this->configManager);
|
||||
if (!$form_state->getUserInput() && $snapshot_comparer->createChangelist()->hasChanges()) {
|
||||
$change_list = [];
|
||||
foreach ($snapshot_comparer->getAllCollectionNames() as $collection) {
|
||||
foreach ($snapshot_comparer->getChangelist(NULL, $collection) as $config_names) {
|
||||
if (empty($config_names)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($config_names as $config_name) {
|
||||
$change_list[] = $config_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
sort($change_list);
|
||||
$message = [
|
||||
[
|
||||
'#markup' => $this->t('The following items in your active configuration have changes since the last import that may be lost on the next import.'),
|
||||
],
|
||||
[
|
||||
'#theme' => 'item_list',
|
||||
'#items' => $change_list,
|
||||
],
|
||||
];
|
||||
$this->messenger()->addWarning($this->renderer->renderPlain($message));
|
||||
}
|
||||
}
|
||||
|
||||
// Store the comparer for use in the submit.
|
||||
$form_state->set('storage_comparer', $storage_comparer);
|
||||
|
||||
// Add the AJAX library to the form for dialog support.
|
||||
$form['#attached']['library'][] = 'core/drupal.dialog.ajax';
|
||||
|
||||
foreach ($storage_comparer->getAllCollectionNames() as $collection) {
|
||||
if ($collection != StorageInterface::DEFAULT_COLLECTION) {
|
||||
$form[$collection]['collection_heading'] = [
|
||||
'#type' => 'html_tag',
|
||||
'#tag' => 'h2',
|
||||
'#value' => $this->t('@collection configuration collection', ['@collection' => $collection]),
|
||||
];
|
||||
}
|
||||
foreach ($storage_comparer->getChangelist(NULL, $collection) as $config_change_type => $config_names) {
|
||||
if (empty($config_names)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// @todo A table caption would be more appropriate, but does not have the
|
||||
// visual importance of a heading.
|
||||
$form[$collection][$config_change_type]['heading'] = [
|
||||
'#type' => 'html_tag',
|
||||
'#tag' => 'h3',
|
||||
];
|
||||
switch ($config_change_type) {
|
||||
case 'create':
|
||||
$form[$collection][$config_change_type]['heading']['#value'] = $this->formatPlural(count($config_names), '@count new', '@count new');
|
||||
break;
|
||||
|
||||
case 'update':
|
||||
$form[$collection][$config_change_type]['heading']['#value'] = $this->formatPlural(count($config_names), '@count changed', '@count changed');
|
||||
break;
|
||||
|
||||
case 'delete':
|
||||
$form[$collection][$config_change_type]['heading']['#value'] = $this->formatPlural(count($config_names), '@count removed', '@count removed');
|
||||
break;
|
||||
|
||||
case 'rename':
|
||||
$form[$collection][$config_change_type]['heading']['#value'] = $this->formatPlural(count($config_names), '@count renamed', '@count renamed');
|
||||
break;
|
||||
}
|
||||
$form[$collection][$config_change_type]['list'] = [
|
||||
'#type' => 'table',
|
||||
'#header' => [$this->t('Name'), $this->t('Operations')],
|
||||
];
|
||||
|
||||
foreach ($config_names as $config_name) {
|
||||
if ($config_change_type == 'rename') {
|
||||
$names = $storage_comparer->extractRenameNames($config_name);
|
||||
$route_options = ['source_name' => $names['old_name'], 'target_name' => $names['new_name']];
|
||||
$config_name = $this->t('@source_name to @target_name', ['@source_name' => $names['old_name'], '@target_name' => $names['new_name']]);
|
||||
}
|
||||
else {
|
||||
$route_options = ['source_name' => $config_name];
|
||||
}
|
||||
if ($collection != StorageInterface::DEFAULT_COLLECTION) {
|
||||
$route_name = 'config.diff_collection';
|
||||
$route_options['collection'] = $collection;
|
||||
}
|
||||
else {
|
||||
$route_name = 'config.diff';
|
||||
}
|
||||
$links['view_diff'] = [
|
||||
'title' => $this->t('View differences'),
|
||||
'url' => Url::fromRoute($route_name, $route_options),
|
||||
'attributes' => [
|
||||
'class' => ['use-ajax'],
|
||||
'data-dialog-type' => 'modal',
|
||||
'data-dialog-options' => json_encode([
|
||||
'width' => 700,
|
||||
]),
|
||||
],
|
||||
];
|
||||
$form[$collection][$config_change_type]['list']['#rows'][] = [
|
||||
'name' => $config_name,
|
||||
'operations' => [
|
||||
'data' => [
|
||||
'#type' => 'operations',
|
||||
'#links' => $links,
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$config_importer = new ConfigImporter(
|
||||
$form_state->get('storage_comparer'),
|
||||
$this->eventDispatcher,
|
||||
$this->configManager,
|
||||
$this->lock,
|
||||
$this->typedConfigManager,
|
||||
$this->moduleHandler,
|
||||
$this->moduleInstaller,
|
||||
$this->themeHandler,
|
||||
$this->getStringTranslation()
|
||||
);
|
||||
if ($config_importer->alreadyImporting()) {
|
||||
$this->messenger()->addStatus($this->t('Another request may be synchronizing configuration already.'));
|
||||
}
|
||||
else {
|
||||
try {
|
||||
$sync_steps = $config_importer->initialize();
|
||||
$batch = [
|
||||
'operations' => [],
|
||||
'finished' => [ConfigImporterBatch::class, 'finish'],
|
||||
'title' => t('Synchronizing configuration'),
|
||||
'init_message' => t('Starting configuration synchronization.'),
|
||||
'progress_message' => t('Completed step @current of @total.'),
|
||||
'error_message' => t('Configuration synchronization has encountered an error.'),
|
||||
];
|
||||
foreach ($sync_steps as $sync_step) {
|
||||
$batch['operations'][] = [[ConfigImporterBatch::class, 'process'], [$config_importer, $sync_step]];
|
||||
}
|
||||
|
||||
batch_set($batch);
|
||||
}
|
||||
catch (ConfigImporterException $e) {
|
||||
// There are validation errors.
|
||||
$this->messenger()->addError($this->t('The configuration cannot be imported because it failed validation for the following reasons:'));
|
||||
foreach ($config_importer->getErrors() as $message) {
|
||||
$this->messenger()->addError($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the config import batch and persists the importer.
|
||||
*
|
||||
* @param \Drupal\Core\Config\ConfigImporter $config_importer
|
||||
* The batch config importer object to persist.
|
||||
* @param string $sync_step
|
||||
* The synchronization step to do.
|
||||
* @param array $context
|
||||
* The batch context.
|
||||
*
|
||||
* @deprecated in Drupal 8.6.0 and will be removed before 9.0.0. Use
|
||||
* \Drupal\Core\Config\Importer\ConfigImporterBatch::process() instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2897299
|
||||
*/
|
||||
public static function processBatch(ConfigImporter $config_importer, $sync_step, &$context) {
|
||||
@trigger_error('\Drupal\config\Form\ConfigSync::processBatch() deprecated in Drupal 8.6.0 and will be removed before 9.0.0. Use \Drupal\Core\Config\Importer\ConfigImporterBatch::process() instead. See https://www.drupal.org/node/2897299');
|
||||
ConfigImporterBatch::process($config_importer, $sync_step, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish batch.
|
||||
*
|
||||
* This function is a static function to avoid serializing the ConfigSync
|
||||
* object unnecessarily.
|
||||
*
|
||||
* @deprecated in Drupal 8.6.0 and will be removed before 9.0.0. Use
|
||||
* \Drupal\Core\Config\Importer\ConfigImporterBatch::finish() instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2897299
|
||||
*/
|
||||
public static function finishBatch($success, $results, $operations) {
|
||||
@trigger_error('\Drupal\config\Form\ConfigSync::finishBatch() deprecated in Drupal 8.6.0 and will be removed before 9.0.0. Use \Drupal\Core\Config\Importer\ConfigImporterBatch::finish() instead. See https://www.drupal.org/node/2897299');
|
||||
ConfigImporterBatch::finish($success, $results, $operations);
|
||||
}
|
||||
|
||||
}
|
||||
203
2017/web/core/modules/config/src/StorageReplaceDataWrapper.php
Normal file
203
2017/web/core/modules/config/src/StorageReplaceDataWrapper.php
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\config;
|
||||
|
||||
use Drupal\Core\Config\StorageInterface;
|
||||
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
|
||||
|
||||
/**
|
||||
* Wraps a configuration storage to allow replacing specific configuration data.
|
||||
*/
|
||||
class StorageReplaceDataWrapper implements StorageInterface {
|
||||
use DependencySerializationTrait;
|
||||
|
||||
/**
|
||||
* The configuration storage to be wrapped.
|
||||
*
|
||||
* @var \Drupal\Core\Config\StorageInterface
|
||||
*/
|
||||
protected $storage;
|
||||
|
||||
/**
|
||||
* The configuration replacement data, keyed by configuration object name.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $replacementData = [];
|
||||
|
||||
/**
|
||||
* The storage collection.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $collection;
|
||||
|
||||
/**
|
||||
* Constructs a new StorageReplaceDataWrapper.
|
||||
*
|
||||
* @param \Drupal\Core\Config\StorageInterface $storage
|
||||
* A configuration storage to be used to read and write configuration.
|
||||
* @param string $collection
|
||||
* (optional) The collection to store configuration in. Defaults to the
|
||||
* default collection.
|
||||
*/
|
||||
public function __construct(StorageInterface $storage, $collection = StorageInterface::DEFAULT_COLLECTION) {
|
||||
$this->storage = $storage;
|
||||
$this->collection = $collection;
|
||||
$this->replacementData[$collection] = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function exists($name) {
|
||||
return isset($this->replacementData[$this->collection][$name]) || $this->storage->exists($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function read($name) {
|
||||
if (isset($this->replacementData[$this->collection][$name])) {
|
||||
return $this->replacementData[$this->collection][$name];
|
||||
}
|
||||
return $this->storage->read($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function readMultiple(array $names) {
|
||||
$data = $this->storage->readMultiple(($names));
|
||||
foreach ($names as $name) {
|
||||
if (isset($this->replacementData[$this->collection][$name])) {
|
||||
$data[$name] = $this->replacementData[$this->collection][$name];
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function write($name, array $data) {
|
||||
if (isset($this->replacementData[$this->collection][$name])) {
|
||||
unset($this->replacementData[$this->collection][$name]);
|
||||
}
|
||||
return $this->storage->write($name, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function delete($name) {
|
||||
if (isset($this->replacementData[$this->collection][$name])) {
|
||||
unset($this->replacementData[$this->collection][$name]);
|
||||
}
|
||||
return $this->storage->delete($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function rename($name, $new_name) {
|
||||
if (isset($this->replacementData[$this->collection][$name])) {
|
||||
$this->replacementData[$this->collection][$new_name] = $this->replacementData[$this->collection][$name];
|
||||
unset($this->replacementData[$this->collection][$name]);
|
||||
}
|
||||
return $this->storage->rename($name, $new_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function encode($data) {
|
||||
return $this->storage->encode($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function decode($raw) {
|
||||
return $this->storage->decode($raw);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function listAll($prefix = '') {
|
||||
$names = $this->storage->listAll($prefix);
|
||||
$additional_names = [];
|
||||
if ($prefix === '') {
|
||||
$additional_names = array_keys($this->replacementData[$this->collection]);
|
||||
}
|
||||
else {
|
||||
foreach (array_keys($this->replacementData[$this->collection]) as $name) {
|
||||
if (strpos($name, $prefix) === 0) {
|
||||
$additional_names[] = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!empty($additional_names)) {
|
||||
$names = array_unique(array_merge($names, $additional_names));
|
||||
}
|
||||
return $names;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function deleteAll($prefix = '') {
|
||||
if ($prefix === '') {
|
||||
$this->replacementData[$this->collection] = [];
|
||||
}
|
||||
else {
|
||||
foreach (array_keys($this->replacementData[$this->collection]) as $name) {
|
||||
if (strpos($name, $prefix) === 0) {
|
||||
unset($this->replacementData[$this->collection][$name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this->storage->deleteAll($prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function createCollection($collection) {
|
||||
return new static(
|
||||
$this->storage->createCollection($collection),
|
||||
$collection
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getAllCollectionNames() {
|
||||
return $this->storage->getAllCollectionNames();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCollectionName() {
|
||||
return $this->collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the configuration object data with the supplied data.
|
||||
*
|
||||
* @param $name
|
||||
* The configuration object name whose data to replace.
|
||||
* @param array $data
|
||||
* The configuration data.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function replaceData($name, array $data) {
|
||||
$this->replacementData[$this->collection][$name] = $data;
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\config\Tests;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\AssertConfigEntityImportTrait is deprecated in Drupal 8.4.1 and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\config\Traits\AssertConfigEntityImportTrait. See https://www.drupal.org/node/2916197.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Core\Config\Entity\ConfigEntityInterface;
|
||||
|
||||
/**
|
||||
* Provides test assertions for testing config entity synchronization.
|
||||
*
|
||||
* Can be used by test classes that extend \Drupal\simpletest\WebTestBase or
|
||||
* \Drupal\KernelTests\KernelTestBase.
|
||||
*
|
||||
* @deprecated in Drupal 8.4.1 and will be removed before Drupal 9.0.0.
|
||||
* Use \Drupal\Tests\config\Traits\AssertConfigEntityImportTrait.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2916197
|
||||
*/
|
||||
trait AssertConfigEntityImportTrait {
|
||||
|
||||
/**
|
||||
* Asserts that a config entity can be imported without changing it.
|
||||
*
|
||||
* @param \Drupal\Core\Config\Entity\ConfigEntityInterface $entity
|
||||
* The config entity to test importing.
|
||||
*/
|
||||
public function assertConfigEntityImport(ConfigEntityInterface $entity) {
|
||||
// Save original config information.
|
||||
$entity_uuid = $entity->uuid();
|
||||
$entity_type_id = $entity->getEntityTypeId();
|
||||
$original_data = $entity->toArray();
|
||||
// Copy everything to sync.
|
||||
$this->copyConfig(\Drupal::service('config.storage'), \Drupal::service('config.storage.sync'));
|
||||
// Delete the configuration from active. Don't worry about side effects of
|
||||
// deleting config like fields cleaning up field storages. The coming import
|
||||
// should recreate everything as necessary.
|
||||
$entity->delete();
|
||||
$this->configImporter()->reset()->import();
|
||||
$imported_entity = \Drupal::entityManager()->loadEntityByUuid($entity_type_id, $entity_uuid);
|
||||
$this->assertIdentical($original_data, $imported_entity->toArray());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\config\Tests;
|
||||
|
||||
/**
|
||||
* Provides a class for checking configuration schema.
|
||||
*
|
||||
* @deprecated as of 8.3.x, will be removed in before Drupal 9.0.0.
|
||||
*/
|
||||
trait SchemaCheckTestTrait {
|
||||
|
||||
use \Drupal\Tests\SchemaCheckTestTrait;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
# Clashes with default configuration provided by the config_test module.
|
||||
id: dotted.default
|
||||
label: 'Config install fail'
|
||||
weight: 0
|
||||
protected_property: Default
|
||||
# Intentionally commented out to verify default status behavior.
|
||||
# status: 1
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
# Clashes with default configuration provided by the config_test module.
|
||||
label: 'Je suis'
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
name: 'Test theme for configuration clash detection'
|
||||
type: theme
|
||||
description: 'Test theme for configuration clash detection'
|
||||
version: VERSION
|
||||
base theme: classy
|
||||
core: 8.x
|
||||
regions:
|
||||
content: Content
|
||||
left: Left
|
||||
right: Right
|
||||
|
|
@ -0,0 +1 @@
|
|||
collection: another_collection
|
||||
|
|
@ -0,0 +1 @@
|
|||
collection: collection.test1
|
||||
|
|
@ -0,0 +1 @@
|
|||
collection: collection.test2
|
||||
|
|
@ -0,0 +1 @@
|
|||
label: entity
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
# This should contain a copy of the configuration from the
|
||||
# config_collection_install_test module.
|
||||
name: 'Config collection clash test module'
|
||||
type: module
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
dependencies:
|
||||
- drupal:config_collection_install_test
|
||||
|
|
@ -0,0 +1 @@
|
|||
collection: another_collection
|
||||
|
|
@ -0,0 +1 @@
|
|||
collection: collection.test1
|
||||
|
|
@ -0,0 +1 @@
|
|||
collection: collection.test2
|
||||
|
|
@ -0,0 +1 @@
|
|||
label: entity
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
config_collection_install_test.test:
|
||||
type: config_object
|
||||
label: 'Collection test'
|
||||
mapping:
|
||||
collection:
|
||||
type: string
|
||||
label: 'Collection'
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
name: 'Configuration events test'
|
||||
type: module
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
services:
|
||||
config_events_test.event_subscriber:
|
||||
class: Drupal\config_collection_install_test\EventSubscriber
|
||||
arguments: ['@state']
|
||||
tags:
|
||||
- { name: event_subscriber }
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\config_collection_install_test;
|
||||
|
||||
use Drupal\Core\Config\ConfigCollectionInfo;
|
||||
use Drupal\Core\Config\ConfigEvents;
|
||||
use Drupal\Core\State\StateInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
class EventSubscriber implements EventSubscriberInterface {
|
||||
|
||||
/**
|
||||
* The state key value store.
|
||||
*
|
||||
* @var \Drupal\Core\State\StateInterface
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* Constructs the Event Subscriber object.
|
||||
*
|
||||
* @param \Drupal\Core\State\StateInterface $state
|
||||
* The state key value store.
|
||||
*/
|
||||
public function __construct(StateInterface $state) {
|
||||
$this->state = $state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reacts to the ConfigEvents::COLLECTION_INFO event.
|
||||
*
|
||||
* @param \Drupal\Core\Config\ConfigCollectionInfo $collection_info
|
||||
* The configuration collection info event.
|
||||
*/
|
||||
public function addCollections(ConfigCollectionInfo $collection_info) {
|
||||
$collections = $this->state->get('config_collection_install_test.collection_names', []);
|
||||
foreach ($collections as $collection) {
|
||||
$collection_info->addCollection($collection);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents() {
|
||||
$events[ConfigEvents::COLLECTION_INFO][] = ['addCollections'];
|
||||
return $events;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
name: 'Configuration entity static cache test'
|
||||
type: module
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Provides configuration entity static cache test helpers.
|
||||
*/
|
||||
|
||||
use Drupal\Component\Utility\Random;
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_load() for 'static_cache_test_config_test'.
|
||||
*/
|
||||
function config_entity_static_cache_test_config_test_load($entities) {
|
||||
static $random;
|
||||
if (!$random) {
|
||||
$random = new Random();
|
||||
}
|
||||
foreach ($entities as $entity) {
|
||||
// Add a random stamp for every load(), so that during tests, we can tell
|
||||
// if an entity was retrieved from cache (unchanged stamp) or reloaded.
|
||||
$entity->_loadStamp = $random->string(8, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_type_alter().
|
||||
*/
|
||||
function config_entity_static_cache_test_entity_type_alter(array &$entity_types) {
|
||||
/** @var $entity_types \Drupal\Core\Entity\EntityTypeInterface[] */
|
||||
$entity_types['config_test']->set('static_cache', TRUE);
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\config_entity_static_cache_test;
|
||||
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Core\Config\ConfigFactoryOverrideInterface;
|
||||
use Drupal\Core\Config\StorageInterface;
|
||||
|
||||
/**
|
||||
* Tests module overrides for configuration.
|
||||
*/
|
||||
class ConfigOverrider implements ConfigFactoryOverrideInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function loadOverrides($names) {
|
||||
return [
|
||||
'config_test.dynamic.test_1' => [
|
||||
'label' => 'Overridden label',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheSuffix() {
|
||||
return 'config_entity_static_cache_test';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function createConfigObject($name, $collection = StorageInterface::DEFAULT_COLLECTION) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheableMetadata($name) {
|
||||
return new CacheableMetadata();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
config_events_test.test:
|
||||
type: config_object
|
||||
label: 'Configuration events test'
|
||||
mapping:
|
||||
key:
|
||||
type: string
|
||||
label: 'Value'
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
name: 'Configuration events test'
|
||||
type: module
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
services:
|
||||
config_events_test.event_subscriber:
|
||||
class: Drupal\config_events_test\EventSubscriber
|
||||
arguments: ['@state']
|
||||
tags:
|
||||
- { name: event_subscriber }
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\config_events_test;
|
||||
|
||||
use Drupal\Core\Config\ConfigCrudEvent;
|
||||
use Drupal\Core\Config\ConfigEvents;
|
||||
use Drupal\Core\State\StateInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
class EventSubscriber implements EventSubscriberInterface {
|
||||
|
||||
/**
|
||||
* The state key value store.
|
||||
*
|
||||
* @var \Drupal\Core\State\StateInterface
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* Constructs the Event Subscriber object.
|
||||
*
|
||||
* @param \Drupal\Core\State\StateInterface $state
|
||||
* The state key value store.
|
||||
*/
|
||||
public function __construct(StateInterface $state) {
|
||||
$this->state = $state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reacts to config event.
|
||||
*
|
||||
* @param \Drupal\Core\Config\ConfigCrudEvent $event
|
||||
* The configuration event.
|
||||
* @param string $name
|
||||
* The event name.
|
||||
*/
|
||||
public function configEventRecorder(ConfigCrudEvent $event, $name) {
|
||||
$config = $event->getConfig();
|
||||
$this->state->set('config_events_test.event', [
|
||||
'event_name' => $name,
|
||||
'current_config_data' => $config->get(),
|
||||
'original_config_data' => $config->getOriginal(),
|
||||
'raw_config_data' => $config->getRawData(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents() {
|
||||
$events[ConfigEvents::SAVE][] = ['configEventRecorder'];
|
||||
$events[ConfigEvents::DELETE][] = ['configEventRecorder'];
|
||||
$events[ConfigEvents::RENAME][] = ['configEventRecorder'];
|
||||
return $events;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
name: 'Configuration import test'
|
||||
type: module
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Provides configuration import test helpers.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Config\ConfigImporter;
|
||||
|
||||
/**
|
||||
* Implements hook_config_import_steps_alter().
|
||||
*/
|
||||
function config_import_test_config_import_steps_alter(&$sync_steps) {
|
||||
$sync_steps[] = '_config_import_test_config_import_steps_alter';
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements configuration synchronization step added by an alter for testing.
|
||||
*
|
||||
* @param array $context
|
||||
* The batch context.
|
||||
* @param \Drupal\Core\Config\ConfigImporter $config_importer
|
||||
* The configuration importer.
|
||||
*/
|
||||
function _config_import_test_config_import_steps_alter(&$context, ConfigImporter $config_importer) {
|
||||
$GLOBALS['hook_config_test']['config_import_steps_alter'] = TRUE;
|
||||
if (\Drupal::state()->get('config_import_steps_alter.error', FALSE)) {
|
||||
$context['results']['errors'][] = '_config_import_test_config_import_steps_alter batch error';
|
||||
$config_importer->logError('_config_import_test_config_import_steps_alter ConfigImporter error');
|
||||
}
|
||||
$context['finished'] = 1;
|
||||
return;
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
services:
|
||||
config_import_test.event_subscriber:
|
||||
class: Drupal\config_import_test\EventSubscriber
|
||||
tags:
|
||||
- { name: event_subscriber }
|
||||
arguments: ['@state']
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\config_import_test;
|
||||
|
||||
use Drupal\Core\Config\ConfigCrudEvent;
|
||||
use Drupal\Core\Config\ConfigEvents;
|
||||
use Drupal\Core\Config\ConfigImporterEvent;
|
||||
use Drupal\Core\Config\Importer\MissingContentEvent;
|
||||
use Drupal\Core\State\StateInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* Config import subscriber for config import events.
|
||||
*/
|
||||
class EventSubscriber implements EventSubscriberInterface {
|
||||
|
||||
/**
|
||||
* The key value store.
|
||||
*
|
||||
* @var \Drupal\Core\State\StateInterface
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* Constructs the event subscriber.
|
||||
*
|
||||
* @param \Drupal\Core\State\StateInterface $state
|
||||
* The key value store.
|
||||
*/
|
||||
public function __construct(StateInterface $state) {
|
||||
$this->state = $state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the configuration to be imported.
|
||||
*
|
||||
* @param \Drupal\Core\Config\ConfigImporterEvent $event
|
||||
* The Event to process.
|
||||
*
|
||||
* @throws \Drupal\Core\Config\ConfigNameException
|
||||
*/
|
||||
public function onConfigImporterValidate(ConfigImporterEvent $event) {
|
||||
if ($this->state->get('config_import_test.config_import_validate_fail', FALSE)) {
|
||||
// Log more than one error to test multiple validation errors.
|
||||
$event->getConfigImporter()->logError('Config import validate error 1.');
|
||||
$event->getConfigImporter()->logError('Config import validate error 2.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the missing content event.
|
||||
*
|
||||
* @param \Drupal\Core\Config\Importer\MissingContentEvent $event
|
||||
* The missing content event.
|
||||
*/
|
||||
public function onConfigImporterMissingContentOne(MissingContentEvent $event) {
|
||||
if ($this->state->get('config_import_test.config_import_missing_content', FALSE) && $this->state->get('config_import_test.config_import_missing_content_one', FALSE) === FALSE) {
|
||||
$missing = $event->getMissingContent();
|
||||
$uuid = key($missing);
|
||||
$this->state->set('config_import_test.config_import_missing_content_one', key($missing));
|
||||
$event->resolveMissingContent($uuid);
|
||||
// Stopping propagation ensures that onConfigImporterMissingContentTwo
|
||||
// will be fired on the next batch step.
|
||||
$event->stopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the missing content event.
|
||||
*
|
||||
* @param \Drupal\Core\Config\Importer\MissingContentEvent $event
|
||||
* The missing content event.
|
||||
*/
|
||||
public function onConfigImporterMissingContentTwo(MissingContentEvent $event) {
|
||||
if ($this->state->get('config_import_test.config_import_missing_content', FALSE) && $this->state->get('config_import_test.config_import_missing_content_two', FALSE) === FALSE) {
|
||||
$missing = $event->getMissingContent();
|
||||
$uuid = key($missing);
|
||||
$this->state->set('config_import_test.config_import_missing_content_two', key($missing));
|
||||
$event->resolveMissingContent($uuid);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reacts to a config save and records information in state for testing.
|
||||
*
|
||||
* @param \Drupal\Core\Config\ConfigCrudEvent $event
|
||||
*/
|
||||
public function onConfigSave(ConfigCrudEvent $event) {
|
||||
$config = $event->getConfig();
|
||||
if ($config->getName() == 'action.settings') {
|
||||
$values = $this->state->get('ConfigImportUITest.action.settings.recursion_limit', []);
|
||||
$values[] = $config->get('recursion_limit');
|
||||
$this->state->set('ConfigImportUITest.action.settings.recursion_limit', $values);
|
||||
}
|
||||
|
||||
if ($config->getName() == 'core.extension') {
|
||||
$installed = $this->state->get('ConfigImportUITest.core.extension.modules_installed', []);
|
||||
$uninstalled = $this->state->get('ConfigImportUITest.core.extension.modules_uninstalled', []);
|
||||
$original = $config->getOriginal('module');
|
||||
$data = $config->get('module');
|
||||
$install = array_diff_key($data, $original);
|
||||
if (!empty($install)) {
|
||||
$installed[] = key($install);
|
||||
}
|
||||
$uninstall = array_diff_key($original, $data);
|
||||
if (!empty($uninstall)) {
|
||||
$uninstalled[] = key($uninstall);
|
||||
}
|
||||
|
||||
$this->state->set('ConfigImportUITest.core.extension.modules_installed', $installed);
|
||||
$this->state->set('ConfigImportUITest.core.extension.modules_uninstalled', $uninstalled);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reacts to a config delete and records information in state for testing.
|
||||
*
|
||||
* @param \Drupal\Core\Config\ConfigCrudEvent $event
|
||||
*/
|
||||
public function onConfigDelete(ConfigCrudEvent $event) {
|
||||
$config = $event->getConfig();
|
||||
if ($config->getName() == 'action.settings') {
|
||||
$value = $this->state->get('ConfigImportUITest.action.settings.delete', 0);
|
||||
$this->state->set('ConfigImportUITest.action.settings.delete', $value + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the methods in this class that should be listeners.
|
||||
*
|
||||
* @return array
|
||||
* An array of event listener definitions.
|
||||
*/
|
||||
public static function getSubscribedEvents() {
|
||||
$events[ConfigEvents::SAVE][] = ['onConfigSave', 40];
|
||||
$events[ConfigEvents::DELETE][] = ['onConfigDelete', 40];
|
||||
$events[ConfigEvents::IMPORT_VALIDATE] = ['onConfigImporterValidate'];
|
||||
$events[ConfigEvents::IMPORT_MISSING_CONTENT] = [['onConfigImporterMissingContentOne'], ['onConfigImporterMissingContentTwo', -100]];
|
||||
return $events;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
foo: bar
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
id: other_module_test_with_dependency
|
||||
label: 'Other module test with dependency'
|
||||
weight: 0
|
||||
style: ''
|
||||
status: true
|
||||
langcode: en
|
||||
protected_property: Default
|
||||
dependencies:
|
||||
enforced:
|
||||
module:
|
||||
- config_other_module_config_test
|
||||
config:
|
||||
- config_test.dynamic.dotted.english
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
id: dependency_for_unmet2
|
||||
label: 'Other module test to test optional config installation'
|
||||
weight: 0
|
||||
style: ''
|
||||
status: true
|
||||
langcode: en
|
||||
protected_property: Default
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
name: 'Config install dependency test'
|
||||
type: module
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Provides hook implementations for testing purposes.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_create.
|
||||
*/
|
||||
function config_install_dependency_test_config_test_create(EntityInterface $entity) {
|
||||
// Add an enforced dependency on this module so that we can test if this is
|
||||
// possible during module installation.
|
||||
$entity->setEnforcedDependencies(['module' => ['config_install_dependency_test']]);
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
id: other_module_test_with_dependency
|
||||
label: 'Other module test with dependency'
|
||||
weight: 0
|
||||
style: ''
|
||||
status: true
|
||||
langcode: en
|
||||
protected_property: Default
|
||||
dependencies:
|
||||
enforced:
|
||||
module:
|
||||
- config_other_module_config_test
|
||||
config:
|
||||
- config_test.dynamic.dotted.english
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
id: yet_another_module_test_with_dependency
|
||||
label: 'Yet anther module test with dependency'
|
||||
weight: 0
|
||||
style: ''
|
||||
status: true
|
||||
langcode: en
|
||||
protected_property: Default
|
||||
dependencies:
|
||||
enforced:
|
||||
module:
|
||||
- config_other_module_config_test
|
||||
config:
|
||||
- config_test.dynamic.dotted.english
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
name: 'Config install double dependency test'
|
||||
type: module
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
# Clashes with default configuration provided by the config_test module.
|
||||
id: dotted.default
|
||||
label: 'Config install fail'
|
||||
weight: 0
|
||||
protected_property: Default
|
||||
# Intentionally commented out to verify default status behavior.
|
||||
# status: 1
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
# Clashes with default configuration provided by the config_test module.
|
||||
label: 'Je suis'
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
name: 'Configuration install fail test'
|
||||
type: module
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
dependencies:
|
||||
- drupal:config_test
|
||||
|
|
@ -0,0 +1 @@
|
|||
foo: 'default setting'
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
id: config_integration_test
|
||||
label: 'Default integration config label'
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
# Schema for the configuration files of the Configuration Integration Test module.
|
||||
|
||||
config_integration_test.settings:
|
||||
type: config_object
|
||||
label: 'Configuration integration test settings'
|
||||
mapping:
|
||||
foo:
|
||||
type: string
|
||||
label: 'Foo'
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
name: 'ConfigTest integration'
|
||||
type: module
|
||||
package: 'Testing'
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
dependencies:
|
||||
- drupal:config_test
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
id: other_module_test
|
||||
label: 'Other module test'
|
||||
weight: 0
|
||||
style: ''
|
||||
status: true
|
||||
langcode: en
|
||||
protected_property: Default
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
id: other_module_test_optional_entity_unmet
|
||||
label: 'Other module test to test optional config installation'
|
||||
weight: 0
|
||||
style: ''
|
||||
status: true
|
||||
langcode: en
|
||||
protected_property: Default
|
||||
dependencies:
|
||||
enforced:
|
||||
config:
|
||||
- config_test.dynamic.other_module_test_unmet
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
id: other_module_test_optional_entity_unmet2
|
||||
label: 'Other module test to test optional config installation'
|
||||
weight: 0
|
||||
style: ''
|
||||
status: true
|
||||
langcode: en
|
||||
protected_property: Default
|
||||
dependencies:
|
||||
enforced:
|
||||
config:
|
||||
- config_test.dynamic.dependency_for_unmet2
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
id: other_module_test_unmet
|
||||
label: 'Other module test to test optional config installation'
|
||||
weight: 0
|
||||
style: ''
|
||||
status: true
|
||||
langcode: en
|
||||
protected_property: Default
|
||||
dependencies:
|
||||
enforced:
|
||||
module:
|
||||
- config_install_dependency_test
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
config_other_module_config_test.weird_simple_config:
|
||||
type: config_object
|
||||
mapping:
|
||||
foo:
|
||||
type: string
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
name: 'Config other module config'
|
||||
type: module
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
id: config_override_test
|
||||
theme: classy
|
||||
weight: 0
|
||||
status: true
|
||||
langcode: en
|
||||
region: content
|
||||
plugin: test_cache
|
||||
settings:
|
||||
label: 'Test HTML block'
|
||||
provider: block_test
|
||||
label_display: visible
|
||||
status: true
|
||||
info: ''
|
||||
view_mode: default
|
||||
dependencies:
|
||||
module:
|
||||
- block_test
|
||||
theme:
|
||||
- classy
|
||||
visibility:
|
||||
request_path:
|
||||
id: request_path
|
||||
pages: ''
|
||||
negate: false
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
name: 'Configuration override integration test'
|
||||
type: module
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
|
||||
dependencies:
|
||||
- drupal:block
|
||||
- drupal:block_test
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
services:
|
||||
cache_context.config_override_integration_test:
|
||||
class: Drupal\config_override_integration_test\Cache\ConfigOverrideIntegrationTestCacheContext
|
||||
tags:
|
||||
- { name: cache.context }
|
||||
config_override_integration_test.config_override:
|
||||
class: Drupal\config_override_integration_test\CacheabilityMetadataConfigOverride
|
||||
tags:
|
||||
- { name: config.factory.override }
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\config_override_integration_test\Cache;
|
||||
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Core\Cache\Context\CacheContextInterface;
|
||||
|
||||
/**
|
||||
* A cache context service intended for the config override integration test.
|
||||
*
|
||||
* Cache context ID: 'config_override_integration_test'.
|
||||
*/
|
||||
class ConfigOverrideIntegrationTestCacheContext implements CacheContextInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getLabel() {
|
||||
return t('Config override integration test');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getContext() {
|
||||
// Default to the 'disabled' state.
|
||||
$state = \Drupal::state()->get('config_override_integration_test.enabled', FALSE) ? 'yes' : 'no';
|
||||
return 'config_override_integration_test.' . $state;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheableMetadata() {
|
||||
// Since this depends on State this can change at any time and is not
|
||||
// cacheable.
|
||||
$metadata = new CacheableMetadata();
|
||||
$metadata->setCacheMaxAge(0);
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\config_override_integration_test;
|
||||
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Core\Config\ConfigFactoryOverrideInterface;
|
||||
use Drupal\Core\Config\StorageInterface;
|
||||
|
||||
/**
|
||||
* Test implementation of a config override that provides cacheability metadata.
|
||||
*/
|
||||
class CacheabilityMetadataConfigOverride implements ConfigFactoryOverrideInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function loadOverrides($names) {
|
||||
$overrides = [];
|
||||
|
||||
// Override the test block depending on the state set in the test.
|
||||
$state = \Drupal::state()->get('config_override_integration_test.enabled', FALSE);
|
||||
if (in_array('block.block.config_override_test', $names) && $state !== FALSE) {
|
||||
$overrides = $overrides + [
|
||||
'block.block.config_override_test' => [
|
||||
'settings' => ['label' => 'Overridden block label'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
return $overrides;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheSuffix() {
|
||||
return 'config_override_integration_test';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function createConfigObject($name, $collection = StorageInterface::DEFAULT_COLLECTION) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheableMetadata($name) {
|
||||
$metadata = new CacheableMetadata();
|
||||
if ($name === 'block.block.config_override_test') {
|
||||
$metadata
|
||||
->setCacheContexts(['config_override_integration_test'])
|
||||
->setCacheTags(['config_override_integration_test_tag']);
|
||||
}
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- block_content
|
||||
theme:
|
||||
- classy
|
||||
id: call_to_action
|
||||
theme: classy
|
||||
region: content
|
||||
weight: null
|
||||
provider: null
|
||||
plugin: 'block_content:d7c9d8ba-663f-41b4-8756-86bc55c44653'
|
||||
settings:
|
||||
id: 'block_content:d7c9d8ba-663f-41b4-8756-86bc55c44653'
|
||||
label: 'Shop for cheap now!'
|
||||
provider: block_content
|
||||
label_display: visible
|
||||
status: true
|
||||
info: ''
|
||||
view_mode: default
|
||||
visibility:
|
||||
request_path:
|
||||
id: request_path
|
||||
pages: ''
|
||||
negate: false
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
threshold:
|
||||
requirements_warning: 172800
|
||||
requirements_error: 1209600
|
||||
logging: 1
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
name: 'Configuration override test'
|
||||
type: module
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
|
||||
dependencies:
|
||||
- drupal:block
|
||||
- drupal:block_content
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
services:
|
||||
cache_context.pirate_day:
|
||||
class: Drupal\config_override_test\Cache\PirateDayCacheContext
|
||||
tags:
|
||||
- { name: cache.context }
|
||||
config_override_test.overrider:
|
||||
class: Drupal\config_override_test\ConfigOverrider
|
||||
tags:
|
||||
- { name: config.factory.override}
|
||||
config_override_test.low_priority_overrider:
|
||||
class: Drupal\config_override_test\ConfigOverriderLowPriority
|
||||
tags:
|
||||
- { name: config.factory.override, priority: -100 }
|
||||
config_override_test.pirate_day_cacheability_metadata_override:
|
||||
class: Drupal\config_override_test\PirateDayCacheabilityMetadataConfigOverride
|
||||
tags:
|
||||
- { name: config.factory.override }
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\config_override_test\Cache;
|
||||
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Core\Cache\Context\CacheContextInterface;
|
||||
|
||||
/**
|
||||
* Defines the PirateDayCacheContext service that allows to cache the booty.
|
||||
*
|
||||
* Cache context ID: 'pirate_day'.
|
||||
*/
|
||||
class PirateDayCacheContext implements CacheContextInterface {
|
||||
|
||||
/**
|
||||
* The length of Pirate Day. It lasts 24 hours.
|
||||
*
|
||||
* This is a simplified test implementation. In a real life Pirate Day module
|
||||
* this data wouldn't be defined in a constant, but calculated in a static
|
||||
* method. If it were Pirate Day it should return the number of seconds until
|
||||
* midnight, and on all other days it should return the number of seconds
|
||||
* until the start of the next Pirate Day.
|
||||
*/
|
||||
const PIRATE_DAY_MAX_AGE = 86400;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getLabel() {
|
||||
return t('Pirate day');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getContext() {
|
||||
$is_pirate_day = static::isPirateDay() ? 'yarr' : 'nay';
|
||||
return "pirate_day." . $is_pirate_day;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not it is Pirate Day.
|
||||
*
|
||||
* To ease testing this is determined with a global variable rather than using
|
||||
* the traditional compass and sextant.
|
||||
*
|
||||
* @return bool
|
||||
* Returns TRUE if it is Pirate Day today.
|
||||
*/
|
||||
public static function isPirateDay() {
|
||||
return !empty($GLOBALS['it_is_pirate_day']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheableMetadata() {
|
||||
return new CacheableMetadata();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\config_override_test;
|
||||
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Core\Config\ConfigFactoryOverrideInterface;
|
||||
|
||||
/**
|
||||
* Tests module overrides for configuration.
|
||||
*/
|
||||
class ConfigOverrider implements ConfigFactoryOverrideInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function loadOverrides($names) {
|
||||
$overrides = [];
|
||||
if (!empty($GLOBALS['config_test_run_module_overrides'])) {
|
||||
if (in_array('system.site', $names)) {
|
||||
$overrides = $overrides + ['system.site' => ['name' => 'ZOMG overridden site name']];
|
||||
}
|
||||
if (in_array('config_override_test.new', $names)) {
|
||||
$overrides = $overrides + ['config_override_test.new' => ['module' => 'override']];
|
||||
}
|
||||
}
|
||||
return $overrides;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheSuffix() {
|
||||
return 'ConfigOverrider';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function createConfigObject($name, $collection = StorageInterface::DEFAULT_COLLECTION) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheableMetadata($name) {
|
||||
return new CacheableMetadata();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\config_override_test;
|
||||
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Core\Config\ConfigFactoryOverrideInterface;
|
||||
use Drupal\Core\Config\StorageInterface;
|
||||
|
||||
/**
|
||||
* Tests module overrides for configuration.
|
||||
*/
|
||||
class ConfigOverriderLowPriority implements ConfigFactoryOverrideInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function loadOverrides($names) {
|
||||
$overrides = [];
|
||||
if (!empty($GLOBALS['config_test_run_module_overrides'])) {
|
||||
if (in_array('system.site', $names)) {
|
||||
$overrides = [
|
||||
'system.site' => [
|
||||
'name' => 'Should not apply because of higher priority listener',
|
||||
// This override should apply because it is not overridden by the
|
||||
// higher priority listener.
|
||||
'slogan' => 'Yay for overrides!',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
return $overrides;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheSuffix() {
|
||||
return 'ConfigOverriderLowPriority';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function createConfigObject($name, $collection = StorageInterface::DEFAULT_COLLECTION) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheableMetadata($name) {
|
||||
return new CacheableMetadata();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\config_override_test;
|
||||
|
||||
use Drupal\config_override_test\Cache\PirateDayCacheContext;
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Core\Config\ConfigFactoryOverrideInterface;
|
||||
use Drupal\Core\Config\StorageInterface;
|
||||
|
||||
/**
|
||||
* Test implementation of a config override that provides cacheability metadata.
|
||||
*/
|
||||
class PirateDayCacheabilityMetadataConfigOverride implements ConfigFactoryOverrideInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function loadOverrides($names) {
|
||||
$overrides = [];
|
||||
|
||||
// Override the theme and the 'call_to_action' block on Pirate Day.
|
||||
if (PirateDayCacheContext::isPirateDay()) {
|
||||
if (in_array('system.theme', $names)) {
|
||||
$overrides = $overrides + ['system.theme' => ['default' => 'pirate']];
|
||||
}
|
||||
if (in_array('block.block.call_to_action', $names)) {
|
||||
$overrides = $overrides + [
|
||||
'block.block.call_to_action' => [
|
||||
'settings' => ['label' => 'Draw yer cutlasses!'],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $overrides;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheSuffix() {
|
||||
return 'PirateDayConfigOverrider';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function createConfigObject($name, $collection = StorageInterface::DEFAULT_COLLECTION) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheableMetadata($name) {
|
||||
$metadata = new CacheableMetadata();
|
||||
$metadata
|
||||
->setCacheContexts(['pirate_day'])
|
||||
->setCacheTags(['pirate-day-tag'])
|
||||
->setCacheMaxAge(PirateDayCacheContext::PIRATE_DAY_MAX_AGE);
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
label: 'Label string'
|
||||
irrelevant: 123
|
||||
indescribable:
|
||||
abc: 789
|
||||
def:
|
||||
- 456
|
||||
- 'abc'
|
||||
xyz: 13.4
|
||||
weight: 27
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
testitem: "Whatever structure there is in this file"
|
||||
testlist:
|
||||
- "the main file has no schema, so individual items"
|
||||
- "will not have any schema information."
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
tests:
|
||||
-
|
||||
plugin_id: boolean
|
||||
value: TRUE
|
||||
-
|
||||
plugin_id: boolean:derivative
|
||||
value: TRUE
|
||||
-
|
||||
plugin_id: string
|
||||
value: 'Foo'
|
||||
-
|
||||
plugin_id: string:derivative
|
||||
value: 'Foo'
|
||||
test_with_parents:
|
||||
-
|
||||
plugin_id: boolean
|
||||
settings:
|
||||
value: TRUE
|
||||
-
|
||||
plugin_id: boolean:derivative
|
||||
settings:
|
||||
value: TRUE
|
||||
-
|
||||
plugin_id: string
|
||||
settings:
|
||||
value: 'Foo'
|
||||
-
|
||||
plugin_id: string:derivative
|
||||
settings:
|
||||
value: 'Foo'
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
testid: 'Test id'
|
||||
testdescription: 'Test description'
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
testid: 'Test id'
|
||||
testdescription: 'Test description'
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
one_level:
|
||||
target_key: key_1
|
||||
testitem: 'text for entry_1'
|
||||
two_levels:
|
||||
target_key: key_2
|
||||
wrapper:
|
||||
testitem: 'text for entry_2'
|
||||
three_levels:
|
||||
target_key: key_3
|
||||
wrapper_1:
|
||||
wrapper_2:
|
||||
testitem: 'text for entry_3'
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
testitem: 'Since this file at least has top level schema in config_test.schema.yml'
|
||||
testlist:
|
||||
- 'Direct string items are identified and other items are'
|
||||
- 'recognized as undefined types.'
|
||||
testnoschema: 12
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
id: third_party
|
||||
label: Default
|
||||
weight: 0
|
||||
protected_property: Default
|
||||
third_party_settings:
|
||||
config_schema_test:
|
||||
integer: 1
|
||||
string: 'string'
|
||||
|
|
@ -0,0 +1,337 @@
|
|||
# Schema for the configuration files of the Configuration Schema Test module.
|
||||
|
||||
config_schema_test.someschema:
|
||||
type: config_object
|
||||
label: 'Schema test data'
|
||||
mapping:
|
||||
testitem:
|
||||
label: 'Test item'
|
||||
testlist:
|
||||
label: 'Test list'
|
||||
|
||||
config_schema_test.someschema.with_parents:
|
||||
label: 'Schema test data with parenting'
|
||||
type: config_object
|
||||
mapping:
|
||||
one_level:
|
||||
label: 'Parenting one level up'
|
||||
type: mapping
|
||||
mapping:
|
||||
target_key:
|
||||
label: 'Key used in parent relation'
|
||||
type: string
|
||||
testitem:
|
||||
type: config_schema_test.someschema.with_parents.[%parent.target_key]
|
||||
two_levels:
|
||||
label: 'Parenting two levels up'
|
||||
type: mapping
|
||||
mapping:
|
||||
target_key:
|
||||
label: 'Key used in parent relation'
|
||||
type: string
|
||||
wrapper:
|
||||
label: 'Wrapper'
|
||||
type: mapping
|
||||
mapping:
|
||||
testitem:
|
||||
type: config_schema_test.someschema.with_parents.[%parent.%parent.target_key]
|
||||
three_levels:
|
||||
label: 'Parenting three levels up'
|
||||
type: mapping
|
||||
mapping:
|
||||
target_key:
|
||||
label: 'Key used in parent relation'
|
||||
type: string
|
||||
wrapper_1:
|
||||
label: 'Wrapper 1'
|
||||
type: mapping
|
||||
mapping:
|
||||
wrapper_2:
|
||||
label: 'Wrapper 2'
|
||||
type: mapping
|
||||
mapping:
|
||||
testitem:
|
||||
type: config_schema_test.someschema.with_parents.[%parent.%parent.%parent.target_key]
|
||||
|
||||
config_schema_test.someschema.with_parents.key_1:
|
||||
label: 'Test item nested one level'
|
||||
type: string
|
||||
config_schema_test.someschema.with_parents.key_2:
|
||||
label: 'Test item nested two levels'
|
||||
type: string
|
||||
config_schema_test.someschema.with_parents.key_3:
|
||||
label: 'Test item nested three levels'
|
||||
type: string
|
||||
|
||||
config_schema_test.someschema.somemodule.*.*:
|
||||
type: config_object
|
||||
label: 'Schema multiple filesystem marker test'
|
||||
mapping:
|
||||
testid:
|
||||
type: string
|
||||
label: 'ID'
|
||||
testdescription:
|
||||
type: text
|
||||
label: 'Description'
|
||||
|
||||
config_schema_test.wildcard_fallback.*:
|
||||
type: config_object
|
||||
label: 'Schema wildcard fallback test'
|
||||
mapping:
|
||||
testid:
|
||||
type: string
|
||||
label: 'ID'
|
||||
testdescription:
|
||||
type: text
|
||||
label: 'Description'
|
||||
|
||||
config_schema_test.schema_data_types:
|
||||
type: config_object
|
||||
label: 'Config test schema'
|
||||
mapping:
|
||||
config_schema_test_integer:
|
||||
type: config_schema_test_integer
|
||||
config_schema_test_integer_empty_string:
|
||||
type: config_schema_test_integer
|
||||
integer:
|
||||
type: integer
|
||||
null_integer:
|
||||
type: integer
|
||||
float:
|
||||
type: float
|
||||
null_float:
|
||||
type: float
|
||||
string:
|
||||
type: string
|
||||
null_string:
|
||||
type: string
|
||||
empty_string:
|
||||
type: string
|
||||
boolean:
|
||||
type: boolean
|
||||
no_type:
|
||||
label: 'No label'
|
||||
mapping:
|
||||
type: mapping
|
||||
mapping:
|
||||
string:
|
||||
type: string
|
||||
sequence:
|
||||
type: sequence
|
||||
sequence:
|
||||
type: boolean
|
||||
sequence_bc:
|
||||
type: sequence
|
||||
sequence:
|
||||
- type: boolean
|
||||
|
||||
config_schema_test_integer:
|
||||
type: integer
|
||||
label: 'Config test integer'
|
||||
|
||||
config_schema_test.ignore:
|
||||
type: config_object
|
||||
label: 'Ignore test'
|
||||
mapping:
|
||||
label:
|
||||
type: label
|
||||
label: 'Label'
|
||||
irrelevant:
|
||||
type: ignore
|
||||
label: 'Irrelevant'
|
||||
indescribable:
|
||||
type: ignore
|
||||
label: 'Indescribable'
|
||||
weight:
|
||||
type: integer
|
||||
label: 'Weight'
|
||||
|
||||
config_schema_test.plugin_types:
|
||||
type: config_object
|
||||
mapping:
|
||||
tests:
|
||||
type: sequence
|
||||
sequence:
|
||||
type: test.plugin_types.[plugin_id]
|
||||
test_with_parents:
|
||||
type: sequence
|
||||
sequence:
|
||||
type: mapping
|
||||
mapping:
|
||||
plugin_id:
|
||||
type: string
|
||||
settings:
|
||||
type: test_with_parents.plugin_types.[%parent.plugin_id]
|
||||
|
||||
test.plugin_types:
|
||||
type: mapping
|
||||
mapping:
|
||||
plugin_id:
|
||||
type: string
|
||||
|
||||
test.plugin_types.boolean:
|
||||
type: mapping
|
||||
mapping:
|
||||
plugin_id:
|
||||
type: string
|
||||
value:
|
||||
type: boolean
|
||||
|
||||
test.plugin_types.boolean:*:
|
||||
type: test.plugin_types.boolean
|
||||
|
||||
test_with_parents.plugin_types.boolean:
|
||||
type: mapping
|
||||
mapping:
|
||||
value:
|
||||
type: boolean
|
||||
|
||||
test_with_parents.plugin_types.boolean:*:
|
||||
type: test_with_parents.plugin_types.boolean
|
||||
|
||||
test.plugin_types.*:
|
||||
type: mapping
|
||||
mapping:
|
||||
plugin_id:
|
||||
type: string
|
||||
value:
|
||||
type: string
|
||||
|
||||
test_with_parents.plugin_types.*:
|
||||
type: mapping
|
||||
mapping:
|
||||
value:
|
||||
type: string
|
||||
|
||||
config_schema_test.hook:
|
||||
type: string
|
||||
|
||||
config_test.dynamic.*.third_party.config_schema_test:
|
||||
type: mapping
|
||||
mapping:
|
||||
integer:
|
||||
type: integer
|
||||
string:
|
||||
type: string
|
||||
|
||||
wrapping.config_schema_test.plugin_types:
|
||||
type: config_object
|
||||
mapping:
|
||||
tests:
|
||||
type: sequence
|
||||
sequence:
|
||||
- type: wrapping.test.plugin_types.[plugin_id]
|
||||
|
||||
wrapping.test.plugin_types.*:
|
||||
type: test.plugin_types.[plugin_id]
|
||||
mapping:
|
||||
wrapper_value:
|
||||
type: string
|
||||
|
||||
test.plugin_types.wrapper:*:
|
||||
type: test.plugin_types
|
||||
mapping:
|
||||
internal_value:
|
||||
type: string
|
||||
|
||||
wrapping.config_schema_test.double_brackets:
|
||||
type: config_object
|
||||
mapping:
|
||||
tests:
|
||||
type: sequence
|
||||
sequence:
|
||||
- type: wrapping.test.double_brackets.[another_key]
|
||||
|
||||
wrapping.test.double_brackets.*:
|
||||
type: test.double_brackets.[foo].[bar]
|
||||
mapping:
|
||||
wrapper_value:
|
||||
type: string
|
||||
|
||||
test.double_brackets.cat.dog:
|
||||
type: test.double_brackets
|
||||
mapping:
|
||||
another_key:
|
||||
type: string
|
||||
foo:
|
||||
type: string
|
||||
bar:
|
||||
type: string
|
||||
|
||||
test.double_brackets.turtle.horse:
|
||||
type: test.double_brackets
|
||||
mapping:
|
||||
another_key:
|
||||
type: integer
|
||||
foo:
|
||||
type: string
|
||||
bar:
|
||||
type: string
|
||||
|
||||
test.double_brackets.*:
|
||||
type: mapping
|
||||
|
||||
wrapping.config_schema_test.other_double_brackets:
|
||||
type: config_object
|
||||
mapping:
|
||||
tests:
|
||||
type: sequence
|
||||
sequence:
|
||||
- type: wrapping.test.other_double_brackets.[id]
|
||||
|
||||
wrapping.test.other_double_brackets.*:
|
||||
type: test.double_brackets.[id]
|
||||
mapping:
|
||||
id:
|
||||
type: string
|
||||
foo:
|
||||
type: string
|
||||
bar:
|
||||
type: string
|
||||
|
||||
test.double_brackets.cat:*.*:
|
||||
type: test.double_brackets.breed
|
||||
|
||||
test.double_brackets.breed:
|
||||
type: test.double_brackets
|
||||
mapping:
|
||||
breed:
|
||||
type: string
|
||||
|
||||
config_schema_test.schema_sequence_sort:
|
||||
type: config_object
|
||||
mapping:
|
||||
keyed_sort:
|
||||
type: sequence
|
||||
orderby: key
|
||||
sequence:
|
||||
- type: string
|
||||
value_sort:
|
||||
type: sequence
|
||||
orderby: value
|
||||
sequence:
|
||||
- type: string
|
||||
no_sort:
|
||||
type: sequence
|
||||
sequence:
|
||||
- type: string
|
||||
complex_sort_value:
|
||||
type: sequence
|
||||
orderby: value
|
||||
sequence:
|
||||
- type: mapping
|
||||
mapping:
|
||||
foo:
|
||||
type: string
|
||||
bar:
|
||||
type: string
|
||||
complex_sort_key:
|
||||
type: sequence
|
||||
orderby: key
|
||||
sequence:
|
||||
- type: mapping
|
||||
mapping:
|
||||
foo:
|
||||
type: string
|
||||
bar:
|
||||
type: string
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
name: 'Configuration schema test'
|
||||
type: module
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
hidden: true
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Tests configuration schema functionality.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_config_schema_info_alter().
|
||||
*/
|
||||
function config_schema_test_config_schema_info_alter(&$definitions) {
|
||||
if (\Drupal::state()->get('config_schema_test_exception_add')) {
|
||||
$definitions['config_schema_test.hook_added_defintion'] = $definitions['config_schema_test.hook'];
|
||||
}
|
||||
if (\Drupal::state()->get('config_schema_test_exception_remove')) {
|
||||
unset($definitions['config_schema_test.hook']);
|
||||
}
|
||||
|
||||
// Since code can not be unloaded only alter the definition if it exists.
|
||||
if (isset($definitions['config_schema_test.hook'])) {
|
||||
$definitions['config_schema_test.hook']['additional_metadata'] = 'new schema info';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
id: dotted.default
|
||||
label: Default
|
||||
weight: 0
|
||||
protected_property: Default
|
||||
# Intentionally commented out to verify default status behavior.
|
||||
# status: 1
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
id: isinstallable
|
||||
label: Default
|
||||
weight: 0
|
||||
protected_property: Default
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
id: default
|
||||
label: Default
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
foo: bar
|
||||
404: herp
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
array: []
|
||||
boolean: true
|
||||
exp: 1.2e+34
|
||||
float: 3.14159
|
||||
float_as_integer: !!float 1
|
||||
hex: 0xC
|
||||
int: 99
|
||||
octal: 0775
|
||||
string: string
|
||||
string_int: '1'
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
llama: llama
|
||||
cat:
|
||||
type: kitten
|
||||
count: 2
|
||||
giraffe:
|
||||
hum1: hum1
|
||||
hum2: hum2
|
||||
uuid: '7C30C50E-641A-4E34-A7F1-46BCFB9BE5A3'
|
||||
|
|
@ -0,0 +1 @@
|
|||
foo: de bar
|
||||
|
|
@ -0,0 +1 @@
|
|||
foo: en bar
|
||||
|
|
@ -0,0 +1 @@
|
|||
foo: fr bar
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
# See \Drupal\config\Tests\ConfigInstallProfileOverrideTest
|
||||
id: override
|
||||
label: Default
|
||||
weight: 0
|
||||
protected_property: Default
|
||||
status: true
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
# See \Drupal\config\Tests\ConfigInstallProfileOverrideTest
|
||||
# This configuration entity has dependencies which would be met.
|
||||
id: override_unmet
|
||||
label: Default
|
||||
weight: 0
|
||||
protected_property: Default
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- tour
|
||||
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue