1<?php 2 3namespace Drupal\config\Form; 4 5use Drupal\Core\Archiver\ArchiveTar; 6use Drupal\Core\Config\StorageInterface; 7use Drupal\Core\File\FileSystemInterface; 8use Drupal\Core\Form\FormBase; 9use Drupal\Core\Form\FormStateInterface; 10use Drupal\Core\Site\Settings; 11use Symfony\Component\DependencyInjection\ContainerInterface; 12 13/** 14 * Defines the configuration import form. 15 * 16 * @internal 17 */ 18class ConfigImportForm extends FormBase { 19 20 /** 21 * The configuration storage. 22 * 23 * @var \Drupal\Core\Config\StorageInterface 24 */ 25 protected $configStorage; 26 27 /** 28 * The file system service. 29 * 30 * @var \Drupal\Core\File\FileSystemInterface 31 */ 32 protected $fileSystem; 33 34 /** 35 * The settings object. 36 * 37 * @var \Drupal\Core\Site\Settings 38 */ 39 protected $settings; 40 41 /** 42 * Constructs a new ConfigImportForm. 43 * 44 * @param \Drupal\Core\Config\StorageInterface $config_storage 45 * The configuration storage. 46 * @param \Drupal\Core\File\FileSystemInterface $file_system 47 * The file system service. 48 * @param \Drupal\Core\Site\Settings $settings 49 * The settings object. 50 */ 51 public function __construct(StorageInterface $config_storage, FileSystemInterface $file_system, Settings $settings) { 52 $this->configStorage = $config_storage; 53 $this->fileSystem = $file_system; 54 $this->settings = $settings; 55 } 56 57 /** 58 * {@inheritdoc} 59 */ 60 public static function create(ContainerInterface $container) { 61 return new static( 62 $container->get('config.storage.sync'), 63 $container->get('file_system'), 64 $container->get('settings') 65 ); 66 } 67 68 /** 69 * {@inheritdoc} 70 */ 71 public function getFormId() { 72 return 'config_import_form'; 73 } 74 75 /** 76 * {@inheritdoc} 77 */ 78 public function buildForm(array $form, FormStateInterface $form_state) { 79 $directory = $this->settings->get('config_sync_directory'); 80 $directory_is_writable = is_writable($directory); 81 if (!$directory_is_writable) { 82 $this->messenger()->addError($this->t('The directory %directory is not writable.', ['%directory' => $directory])); 83 } 84 $form['import_tarball'] = [ 85 '#type' => 'file', 86 '#title' => $this->t('Configuration archive'), 87 '#description' => $this->t('Allowed types: @extensions.', ['@extensions' => 'tar.gz tgz tar.bz2']), 88 ]; 89 90 $form['submit'] = [ 91 '#type' => 'submit', 92 '#value' => $this->t('Upload'), 93 '#disabled' => !$directory_is_writable, 94 ]; 95 return $form; 96 } 97 98 /** 99 * {@inheritdoc} 100 */ 101 public function validateForm(array &$form, FormStateInterface $form_state) { 102 $all_files = $this->getRequest()->files->get('files', []); 103 if (!empty($all_files['import_tarball'])) { 104 $file_upload = $all_files['import_tarball']; 105 if ($file_upload->isValid()) { 106 $form_state->setValue('import_tarball', $file_upload->getRealPath()); 107 return; 108 } 109 } 110 111 $form_state->setErrorByName('import_tarball', $this->t('The file could not be uploaded.')); 112 } 113 114 /** 115 * {@inheritdoc} 116 */ 117 public function submitForm(array &$form, FormStateInterface $form_state) { 118 if ($path = $form_state->getValue('import_tarball')) { 119 $this->configStorage->deleteAll(); 120 try { 121 $archiver = new ArchiveTar($path, 'gz'); 122 $files = []; 123 foreach ($archiver->listContent() as $file) { 124 $files[] = $file['filename']; 125 } 126 $archiver->extractList($files, $this->settings->get('config_sync_directory'), '', FALSE, FALSE); 127 $this->messenger()->addStatus($this->t('Your configuration files were successfully uploaded and are ready for import.')); 128 $form_state->setRedirect('config.sync'); 129 } 130 catch (\Exception $e) { 131 $this->messenger()->addError($this->t('Could not extract the contents of the tar file. The error message is <em>@message</em>', ['@message' => $e->getMessage()])); 132 } 133 $this->fileSystem->unlink($path); 134 } 135 } 136 137} 138