diff -u b/core/modules/config/lib/Drupal/config/Form/ConfigSync.php b/core/modules/config/lib/Drupal/config/Form/ConfigSync.php --- b/core/modules/config/lib/Drupal/config/Form/ConfigSync.php +++ b/core/modules/config/lib/Drupal/config/Form/ConfigSync.php @@ -7,14 +7,18 @@ namespace Drupal\config\Form; -use Drupal\Core\ControllerInterface; -use Drupal\Core\Database\Connection; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; + +use Drupal\Core\Controller\ControllerInterface; use Drupal\Core\Form\FormInterface; use Drupal\Core\Config\StorageInterface; -use Drupal\Core\Ajax\AjaxResponse; -use Drupal\Core\Ajax\OpenModalDialogCommand; use Drupal\Core\Lock\LockBackendInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; +use Drupal\Core\Config\StorageComparer; +use Drupal\Core\Config\ConfigImporter; +use Drupal\Core\Config\ConfigException; +use Drupal\Core\Config\ConfigFactory; +use \Drupal\Core\Entity\EntityManager; /** * Construct the storage changes in a configuration synchronization form. @@ -22,13 +26,6 @@ class ConfigSync implements ControllerInterface, FormInterface { /** - * The database connection object. - * - * @var \Drupal\Core\Database\Connection - */ - protected $database; - - /** * The database lock object. * * @var \Drupal\Core\Lock\LockBackendInterface @@ -50,7 +47,24 @@ protected $targetStorage; /** - * Constructs a database object. + * Event dispatcher. + * + * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface + */ + protected $eventDispatcher; + + /** + * @var \Drupal\Core\Config\ConfigFactory; + */ + protected $configFactory; + + /** + * @var \Drupal\Core\Entity\EntityManager; + */ + protected $entity_manager; + + /** + * Constructs the object. * * @param \Drupal\Core\Database\Connection; $database * The database object. @@ -60,12 +74,20 @@ * The target storage manager. * @param \Drupal\Core\Lock\LockBackendInterface $lock * The lock object. + * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher + * Event dispatcher. + * @param \Drupal\Core\Config\ConfigFactory $config_factory + * Configuration object factory. + * @param \Drupal\Core\Entity\EntityManager + * Entity manager. */ - public function __construct(Connection $database, StorageInterface $sourceStorage, StorageInterface $targetStorage, LockBackendInterface $lock) { - $this->database = $database; + public function __construct(StorageInterface $sourceStorage, StorageInterface $targetStorage, LockBackendInterface $lock, EventDispatcherInterface $event_dispatcher, ConfigFactory $config_factory, EntityManager $entity_manger) { $this->sourceStorage = $sourceStorage; $this->targetStorage = $targetStorage; $this->lock = $lock; + $this->eventDispatcher = $event_dispatcher; + $this->configFactory = $config_factory; + $this->entity_manager = $entity_manger; } /** @@ -73,10 +95,12 @@ */ public static function create(ContainerInterface $container) { return new static( - $container->get('database'), $container->get('config.storage.staging'), $container->get('config.storage'), - $container->get('lock') + $container->get('lock'), + $container->get('event_dispatcher'), + $container->get('config.factory'), + $container->get('plugin.manager.entity') ); } @@ -106,23 +130,30 @@ * {@inheritdoc} */ public function submitForm(array &$form, array &$form_state) { - if (!$this->lock->lockMayBeAvailable(CONFIG_IMPORT_LOCK)) { + $config_importer = new ConfigImporter( + $form_state['storage_comparer'], + $this->eventDispatcher, + $this->configFactory, + $this->entity_manager, + $this->lock + ); + if ($config_importer->alreadyImporting()) { drupal_set_message(t('Another request may be synchronizing configuration already.')); } - else if (config_import()) { - // Once a sync completes, we empty the staging directory. This prevents - // changes from being accidentally overwritten by stray files getting - // imported later. - foreach ($this->sourceStorage->listAll() as $name) { - $this->sourceStorage->delete($name); + else{ + try { + $config_importer->import(); + drupal_flush_all_caches(); + drupal_set_message(t('The configuration was imported successfully.')); + } + catch (ConfigException $e) { + // Return a negative result for UI purposes. We do not differentiate between + // an actual synchronization error and a failed lock, because concurrent + // synchronizations are an edge-case happening only when multiple developers + // or site builders attempt to do it without coordinating. + watchdog_exception('config_import', $e); + drupal_set_message(t('The import failed due to an error. Any errors have been logged.'), 'error'); } - - drupal_flush_all_caches(); - - drupal_set_message(t('The configuration was imported successfully.')); - } - else { - drupal_set_message(t('The import failed due to an error. Any errors have been logged.'), 'error'); } } @@ -142,34 +173,31 @@ */ private function config_admin_sync_form(array &$form, array &$form_state) { $source_list = $this->sourceStorage->listAll(); - if (empty($source_list)) { + $config_comparer = new StorageComparer($this->sourceStorage, $this->targetStorage); + if (empty($source_list) || !$config_comparer->createChangelist()->hasChanges()) { $form['no_changes'] = array( - '#markup' => t('There is no configuration to import.'), + '#markup' => t('There are no configuration changes.'), ); $form['actions']['#access'] = FALSE; return $form; } - - $config_changes = config_sync_get_changes($this->sourceStorage, $this->targetStorage); - if (empty($config_changes)) { - $form['no_changes'] = array( - '#markup' => t('There are no configuration changes.'), - ); - return $form; + else { + // Store the comparer for use in the submit. + $form_state['storage_comparer'] = $config_comparer; } // Add the AJAX library to the form for dialog support. $form['#attached']['library'][] = array('system', 'drupal.ajax'); - foreach ($config_changes as $config_change_type => $config_files) { + foreach ($config_comparer->getChangelist() as $config_change_type => $config_files) { if (empty($config_files)) { continue; } // @todo A table caption would be more appropriate, but does not have the - // visual importance of a heading. + // visual importance of a heading. $form[$config_change_type]['heading'] = array( - '#theme' => 'html_tag__h3', + '#type' => 'html_tag', '#tag' => 'h3', ); switch ($config_change_type) { @@ -177,7 +205,7 @@ $form[$config_change_type]['heading']['#value'] = format_plural(count($config_files), '@count new', '@count new'); break; - case 'change': + case 'update': $form[$config_change_type]['heading']['#value'] = format_plural(count($config_files), '@count changed', '@count changed'); break;