示例#1
0
 /**
  * {@inheritdoc}
  */
 public function submitForm(array &$form, FormStateInterface $form_state)
 {
     global $config_directories, $install_state;
     $sync_directory = $form_state->getValue('sync_directory');
     if ($sync_directory != config_get_config_directory(CONFIG_SYNC_DIRECTORY)) {
         $settings['config_directories'][CONFIG_SYNC_DIRECTORY] = (object) array('value' => $sync_directory, 'required' => TRUE);
         drupal_rewrite_settings($settings);
         $config_directories[CONFIG_SYNC_DIRECTORY] = $sync_directory;
     }
     if ($path = $form_state->getValue('import_tarball')) {
         // Ensure that we have an empty directory if we're going.
         $sync = new FileStorage($sync_directory);
         $sync->deleteAll();
         try {
             $archiver = new ArchiveTar($path, 'gz');
             $files = array();
             foreach ($archiver->listContent() as $file) {
                 $files[] = $file['filename'];
             }
             $archiver->extractList($files, config_get_config_directory(CONFIG_SYNC_DIRECTORY));
             drupal_set_message($this->t('Your configuration files were successfully uploaded, ready for import.'));
         } catch (\Exception $e) {
             drupal_set_message($this->t('Could not extract the contents of the tar file. The error message is <em>@message</em>', array('@message' => $e->getMessage())), 'error');
         }
         drupal_unlink($path);
     }
     // Change the langcode to the site default langcode provided by the
     // configuration.
     $config_storage = new FileStorage(config_get_config_directory(CONFIG_SYNC_DIRECTORY));
     $install_state['parameters']['langcode'] = $config_storage->read('system.site')['langcode'];
 }
 /**
  * {@inheritdoc}
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $messageHelper = $this->getHelperSet()->get('message');
     $directory = $input->getArgument('directory');
     if (!$directory) {
         $config = $this->getConfigFactory()->get('system.file');
         $directory = $config->get('path.temporary') ?: file_directory_temp();
         $directory .= '/' . CONFIG_STAGING_DIRECTORY;
     }
     if (!is_dir($directory)) {
         mkdir($directory, 0777, true);
     }
     $config_export_file = $directory . '/config.tar.gz';
     file_unmanaged_delete($config_export_file);
     try {
         $archiver = new ArchiveTar($config_export_file, 'gz');
         $this->configManager = $this->getConfigManager();
         // 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()));
         }
         $this->targetStorage = $this->getConfigStorage();
         // 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)));
             }
         }
     } catch (\Exception $e) {
         $output->writeln('[+] <error>' . $e->getMessage() . '</error>');
         return;
     }
     $messageHelper->addSuccessMessage(sprintf($this->trans('commands.config.export.messages.directory'), $config_export_file));
 }
示例#3
0
 /**
  * {@inheritdoc}
  */
 public function listContents()
 {
     $files = array();
     foreach ($this->tar->listContent() as $file_data) {
         $files[] = $file_data['filename'];
     }
     return $files;
 }
 /**
  * Writes a file to the file system, creating its directory as needed.
  *
  * @param string $directory
  *   The extension's directory.
  * @param array $file
  *   Array with the following keys:
  *   - 'filename': the name of the file.
  *   - 'subdirectory': any subdirectory of the file within the extension
  *      directory.
  *   - 'string': the contents of the file.
  * @param ArchiveTar $archiver
  *   The archiver.
  *
  * @throws Exception
  */
 protected function generateFile($directory, array $file, ArchiveTar $archiver)
 {
     $filename = $directory;
     if (!empty($file['subdirectory'])) {
         $filename .= '/' . $file['subdirectory'];
     }
     $filename .= '/' . $file['filename'];
     // Set the mode to 0644 rather than the default of 0600.
     if ($archiver->addString($filename, $file['string'], FALSE, ['mode' => 0644]) === FALSE) {
         throw new \Exception($this->t('Failed to archive file @filename.', ['@filename' => $file['filename']]));
     }
 }
示例#5
0
 /**
  * Extracts the contents of the archive file into the config directory.
  *
  * @param DrupalStyle $io
  *   IO object to print messages.
  * @param string $archiveFile
  *   The archive file to extract
  * @param string $configDir
  *   The directory to extract the files into.
  *
  * @return \Drupal\Core\Archiver\ArchiveTar
  *   The initialised object.
  *
  * @throws \Exception
  *   If something went wrong during extraction.
  */
 private function extractArchive(DrupalStyle $io, $archiveFile, $configDir)
 {
     $archiveTar = new ArchiveTar($archiveFile, 'gz');
     $io->simple($this->trans('commands.config.import.messages.config_files_imported'));
     foreach ($archiveTar->listContent() as $file) {
         $io->info('[-] ' . $file['filename']);
     }
     try {
         $archiveTar->extract($configDir . '/');
     } catch (\Exception $e) {
         $io->error($e->getMessage());
         return;
     }
 }
示例#6
0
 /**
  * {@inheritdoc}
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $io = new DrupalStyle($input, $output);
     $directory = $input->getOption('directory');
     $tar = $input->getOption('tar');
     $removeUuid = $input->getOption('remove-uuid');
     if (!$directory) {
         $directory = config_get_config_directory(CONFIG_SYNC_DIRECTORY);
     }
     if ($tar) {
         if (!is_dir($directory)) {
             mkdir($directory, 0777, true);
         }
         $dateTime = new \DateTime();
         $archiveFile = sprintf('%s/config-%s.tar.gz', $directory, $dateTime->format('Y-m-d-H-i-s'));
         $archiveTar = new ArchiveTar($archiveFile, 'gz');
     }
     try {
         // Get raw configuration data without overrides.
         foreach ($this->configManager->getConfigFactory()->listAll() as $name) {
             $configData = $this->configManager->getConfigFactory()->get($name)->getRawData();
             $configName = sprintf('%s.yml', $name);
             // The _core is site-specific, so don't export it.
             unset($configData['_core']);
             if ($removeUuid) {
                 unset($configData['uuid']);
             }
             $ymlData = Yaml::encode($configData);
             if ($tar) {
                 $archiveTar->addString($configName, $ymlData);
                 continue;
             }
             $configFileName = sprintf('%s/%s', $directory, $configName);
             $fileSystem = new Filesystem();
             try {
                 $fileSystem->mkdir($directory);
             } catch (IOExceptionInterface $e) {
                 $io->error(sprintf($this->trans('commands.config.export.messages.error'), $e->getPath()));
             }
             file_put_contents($configFileName, $ymlData);
         }
     } catch (\Exception $e) {
         $io->error($e->getMessage());
     }
     $io->info(sprintf($this->trans('commands.config.export.messages.directory'), $directory));
 }
示例#7
0
 /**
  * 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(array('file' => 'config.tar.gz'));
     return $this->fileDownloadController->download($request, 'temporary');
 }
 /**
  * {@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 = array();
             foreach ($archiver->listContent() as $file) {
                 $files[] = $file['filename'];
             }
             $archiver->extractList($files, config_get_config_directory(CONFIG_STAGING_DIRECTORY));
             drupal_set_message($this->t('Your configuration files were successfully uploaded, ready for import.'));
             $form_state->setRedirect('config.sync');
         } catch (\Exception $e) {
             drupal_set_message($this->t('Could not extract the contents of the tar file. The error message is <em>@message</em>', array('@message' => $e->getMessage())), 'error');
         }
         drupal_unlink($path);
     }
 }
 /**
  * {@inheritdoc}
  */
 protected function setUpSyncForm()
 {
     // Create a new sync directory.
     drupal_mkdir($this->sync_dir);
     // Extract the tarball into the sync directory.
     $archiver = new ArchiveTar($this->tarball, 'gz');
     $files = array();
     foreach ($archiver->listContent() as $file) {
         $files[] = $file['filename'];
     }
     $archiver->extractList($files, $this->sync_dir);
     // Change the user.settings::register so that we can test that
     // standard_install() does not override it.
     $sync = new FileStorage($this->sync_dir);
     $user_settings = $sync->read('user.settings');
     $user_settings['register'] = USER_REGISTER_ADMINISTRATORS_ONLY;
     $sync->write('user.settings', $user_settings);
     $this->drupalPostForm(NULL, array('sync_directory' => drupal_realpath($this->sync_dir)), 'Save and continue');
 }
示例#10
0
 /**
  * {@inheritdoc}
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $config_file = $input->getArgument('config-file');
     $copy_only = $input->getOption('copy-only');
     try {
         $files = array();
         $archiver = new ArchiveTar($config_file, 'gz');
         $output->writeln($this->trans('commands.config.import.messages.config_files_imported'));
         foreach ($archiver->listContent() as $file) {
             $pathinfo = pathinfo($file['filename']);
             $files[$pathinfo['filename']] = $file['filename'];
             $output->writeln('[-] <info>' . $file['filename'] . '</info>');
         }
         $config_staging_dir = config_get_config_directory(CONFIG_SYNC_DIRECTORY);
         try {
             $archiver->extract($config_staging_dir . '/');
         } catch (\Exception $e) {
             $output->writeln('[+] <error>' . $e->getMessage() . '</error>');
             return;
         }
         if ($copy_only) {
             $output->writeln(sprintf($this->trans('commands.config.import.messages.copied'), CONFIG_SYNC_DIRECTORY));
         } else {
             foreach ($files as $cofig_name => $filename) {
                 $config = $this->getConfigFactory()->getEditable($cofig_name);
                 $parser = new Parser();
                 $config_value = $parser->parse(file_get_contents($config_staging_dir . '/' . $filename));
                 $config->setData($config_value);
                 try {
                     $config->save();
                 } catch (\Exception $e) {
                     $output->writeln('[+] <error>' . $e->getMessage() . '</error>');
                     return;
                 }
             }
             $output->writeln(sprintf($this->trans('commands.config.import.messages.imported'), CONFIG_SYNC_DIRECTORY));
         }
     } catch (\Exception $e) {
         $output->writeln('[+] <error>' . $e->getMessage() . '</error>');
         return;
     }
 }
示例#11
0
 /**
  * {@inheritdoc}
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $io = new DrupalStyle($input, $output);
     $configFile = $input->getOption('file');
     $removeFiles = $input->getOption('remove-files');
     $configSyncDir = config_get_config_directory(CONFIG_SYNC_DIRECTORY);
     if ($configFile) {
         $archiveTar = new ArchiveTar($configFile, 'gz');
         $io->simple($this->trans('commands.config.import.messages.config_files_imported'));
         foreach ($archiveTar->listContent() as $file) {
             $io->info('[-] ' . $file['filename']);
         }
         try {
             $archiveTar->extract($configSyncDir . '/');
         } catch (\Exception $e) {
             $io->error($e->getMessage());
             return;
         }
     }
     $finder = new Finder();
     $finder->in($configSyncDir);
     $finder->name("*.yml");
     foreach ($finder as $configFile) {
         $configName = $configFile->getBasename('.yml');
         $configFilePath = sprintf('%s/%s', $configSyncDir, $configFile->getBasename());
         $config = $this->getConfigFactory()->getEditable($configName);
         $parser = new Parser();
         $configData = $parser->parse(file_get_contents($configFilePath));
         $config->setData($configData);
         if ($removeFiles) {
             file_unmanaged_delete($configFilePath);
         }
         try {
             $config->save();
         } catch (\Exception $e) {
             $io->error($e->getMessage());
             return;
         }
     }
     $io->success(sprintf($this->trans('commands.config.import.messages.imported'), CONFIG_SYNC_DIRECTORY));
 }
示例#12
0
 /**
  * {@inheritdoc}
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $messageHelper = $this->getMessageHelper();
     $directory = $input->getOption('directory');
     $tar = $input->getOption('tar');
     $archiveTar = new ArchiveTar();
     if (!$directory) {
         $directory = config_get_config_directory(CONFIG_SYNC_DIRECTORY);
     }
     if ($tar) {
         if (!is_dir($directory)) {
             mkdir($directory, 0777, true);
         }
         $dateTime = new \DateTime();
         $archiveFile = sprintf('%s/config-%s.tar.gz', $directory, $dateTime->format('Y-m-d-H-i-s'));
         $archiveTar = new ArchiveTar($archiveFile, 'gz');
     }
     try {
         $configManager = $this->getConfigManager();
         // Get raw configuration data without overrides.
         foreach ($configManager->getConfigFactory()->listAll() as $name) {
             $configData = $configManager->getConfigFactory()->get($name)->getRawData();
             $configName = sprintf('%s.yml', $name);
             $ymlData = Yaml::encode($configData);
             if ($tar) {
                 $archiveTar->addString($configName, $ymlData);
                 continue;
             }
             $configFileName = sprintf('%s/%s', $directory, $configName);
             file_put_contents($configFileName, $ymlData);
         }
     } catch (\Exception $e) {
         $output->writeln('[+] <error>' . $e->getMessage() . '</error>');
         return;
     }
     $messageHelper->addSuccessMessage(sprintf($this->trans('commands.config.export.messages.directory')));
     $messageHelper->addSuccessMessage($directory);
 }
示例#13
0
 /**
  * @param $migration
  */
 protected function archiveSite(&$migration)
 {
     $exclude = $this->exclude($migration);
     $files = $this->filesToBackup(DRUPAL_ROOT, $exclude);
     if (!empty($files) && isset($migration['file'])) {
         $this->validateArchiveFiles($migration, $files);
         if ($migration['error'] != FALSE) {
             return;
         }
         $dest_file = $migration['file'] . '.tar';
         if (!empty($migration['compression_ext'])) {
             $dest_file .= '.' . $migration['compression_ext'];
         }
         $gz = new Archiver\ArchiveTar($dest_file, $migration['compression_ext'] ? $migration['compression_ext'] : NULL);
         if (!empty($migration['db_file'])) {
             // Add db file.
             $ret = $gz->addModify(array($migration['db_file']), '', $migration['dir'] . DIRECTORY_SEPARATOR);
         }
         // Remove Drupal root from the file paths, OS dependent.
         if (defined('OS_WINDOWS')) {
             $remove_dir = DRUPAL_ROOT . '\\';
         } else {
             $remove_dir = DRUPAL_ROOT . '/';
         }
         $ret = $gz->addModify($files, '', $remove_dir);
         $migration['tar_file'] = $dest_file;
     } else {
         $migration['error'] = TRUE;
     }
 }
 /**
  * Tests an export and import of collections.
  */
 public function testExportImportCollections()
 {
     /** @var \Drupal\Core\Config\StorageInterface $active_storage */
     $active_storage = \Drupal::service('config.storage');
     $test1_storage = $active_storage->createCollection('collection.test1');
     $test1_storage->write('config_test.create', array('foo' => 'bar'));
     $test1_storage->write('config_test.update', array('foo' => 'bar'));
     $test2_storage = $active_storage->createCollection('collection.test2');
     $test2_storage->write('config_test.another_create', array('foo' => 'bar'));
     $test2_storage->write('config_test.another_update', array('foo' => 'bar'));
     // Export the configuration.
     $this->drupalPostForm('admin/config/development/configuration/full/export', array(), 'Export');
     $this->tarball = $this->drupalGetContent();
     $filename = file_directory_temp() . '/' . $this->randomName();
     file_put_contents($filename, $this->tarball);
     // Set up the active storage collections to test import.
     $test1_storage->delete('config_test.create');
     $test1_storage->write('config_test.update', array('foo' => 'baz'));
     $test1_storage->write('config_test.delete', array('foo' => 'bar'));
     $test2_storage->delete('config_test.another_create');
     $test2_storage->write('config_test.another_update', array('foo' => 'baz'));
     $test2_storage->write('config_test.another_delete', array('foo' => 'bar'));
     // Create a snapshot.
     $snapshot_storage = \Drupal::service('config.storage.snapshot');
     \Drupal::service('config.manager')->createSnapshot($active_storage, $snapshot_storage);
     // Ensure that the snapshot has the expected collection data before import.
     $test1_snapshot = $snapshot_storage->createCollection('collection.test1');
     $data = $test1_snapshot->read('config_test.delete');
     $this->assertEqual($data, array('foo' => 'bar'), 'The config_test.delete in collection.test1 exists in the snapshot storage.');
     $data = $test1_snapshot->read('config_test.update');
     $this->assertEqual($data, array('foo' => 'baz'), 'The config_test.update in collection.test1 exists in the snapshot storage.');
     $this->assertFalse($test1_snapshot->read('config_test.create'), 'The config_test.create in collection.test1 does not exist in the snapshot storage.');
     $test2_snapshot = $snapshot_storage->createCollection('collection.test2');
     $data = $test2_snapshot->read('config_test.another_delete');
     $this->assertEqual($data, array('foo' => 'bar'), 'The config_test.another_delete in collection.test2 exists in the snapshot storage.');
     $data = $test2_snapshot->read('config_test.another_update');
     $this->assertEqual($data, array('foo' => 'baz'), 'The config_test.another_update in collection.test2 exists in the snapshot storage.');
     $this->assertFalse($test2_snapshot->read('config_test.another_create'), 'The config_test.another_create in collection.test2 does not exist in the snapshot storage.');
     // Create the tar contains the expected contect for the collections.
     $tar = new ArchiveTar($filename, 'gz');
     $content_list = $tar->listContent();
     // Convert the list of files into something easy to search.
     $files = array();
     foreach ($content_list as $file) {
         $files[] = $file['filename'];
     }
     $this->assertTrue(in_array('collection/test1/config_test.create.yml', $files), 'Config export contains collection/test1/config_test.create.yml.');
     $this->assertTrue(in_array('collection/test2/config_test.another_create.yml', $files), 'Config export contains collection/test2/config_test.another_create.yml.');
     $this->assertTrue(in_array('collection/test1/config_test.update.yml', $files), 'Config export contains collection/test1/config_test.update.yml.');
     $this->assertTrue(in_array('collection/test2/config_test.another_update.yml', $files), 'Config export contains collection/test2/config_test.another_update.yml.');
     $this->assertFalse(in_array('collection/test1/config_test.delete.yml', $files), 'Config export does not contain collection/test1/config_test.delete.yml.');
     $this->assertFalse(in_array('collection/test2/config_test.another_delete.yml', $files), 'Config export does not contain collection/test2/config_test.another_delete.yml.');
     $this->drupalPostForm('admin/config/development/configuration/full/import', array('files[import_tarball]' => $filename), 'Upload');
     // Verify that there are configuration differences to import.
     $this->drupalGet('admin/config/development/configuration');
     $this->assertNoText(t('There are no configuration changes.'));
     $this->assertText(t('!collection configuration collection', array('!collection' => 'collection.test1')));
     $this->assertText(t('!collection configuration collection', array('!collection' => 'collection.test2')));
     $this->assertText('config_test.create');
     $this->assertLinkByHref('admin/config/development/configuration/sync/diff_collection/collection.test1/config_test.create');
     $this->assertText('config_test.update');
     $this->assertLinkByHref('admin/config/development/configuration/sync/diff_collection/collection.test1/config_test.update');
     $this->assertText('config_test.delete');
     $this->assertLinkByHref('admin/config/development/configuration/sync/diff_collection/collection.test1/config_test.delete');
     $this->assertText('config_test.another_create');
     $this->assertLinkByHref('admin/config/development/configuration/sync/diff_collection/collection.test2/config_test.another_create');
     $this->assertText('config_test.another_update');
     $this->assertLinkByHref('admin/config/development/configuration/sync/diff_collection/collection.test2/config_test.another_update');
     $this->assertText('config_test.another_delete');
     $this->assertLinkByHref('admin/config/development/configuration/sync/diff_collection/collection.test2/config_test.another_delete');
     $this->drupalPostForm(NULL, array(), 'Import all');
     $this->assertText(t('There are no configuration changes.'));
     // Test data in collections.
     $data = $test1_storage->read('config_test.create');
     $this->assertEqual($data, array('foo' => 'bar'), 'The config_test.create in collection.test1 has been created.');
     $data = $test1_storage->read('config_test.update');
     $this->assertEqual($data, array('foo' => 'bar'), 'The config_test.update in collection.test1 has been updated.');
     $this->assertFalse($test1_storage->read('config_test.delete'), 'The config_test.delete in collection.test1 has been deleted.');
     $data = $test2_storage->read('config_test.another_create');
     $this->assertEqual($data, array('foo' => 'bar'), 'The config_test.another_create in collection.test2 has been created.');
     $data = $test2_storage->read('config_test.another_update');
     $this->assertEqual($data, array('foo' => 'bar'), 'The config_test.another_update in collection.test2 has been updated.');
     $this->assertFalse($test2_storage->read('config_test.another_delete'), 'The config_test.another_delete in collection.test2 has been deleted.');
     // Ensure that the snapshot has been updated with the collection data.
     $snapshot_storage = \Drupal::service('config.storage.snapshot');
     $test1_snapshot = $snapshot_storage->createCollection('collection.test1');
     $data = $test1_snapshot->read('config_test.create');
     $this->assertEqual($data, array('foo' => 'bar'), 'The config_test.create in collection.test1 has been created in the snapshot storage.');
     $data = $test1_snapshot->read('config_test.update');
     $this->assertEqual($data, array('foo' => 'bar'), 'The config_test.update in collection.test1 has been updated in the snapshot storage.');
     $this->assertFalse($test1_snapshot->read('config_test.delete'), 'The config_test.delete in collection.test1 does not exist in the snapshot storage.');
     $test2_snapshot = $snapshot_storage->createCollection('collection.test2');
     $data = $test2_snapshot->read('config_test.another_create');
     $this->assertEqual($data, array('foo' => 'bar'), 'The config_test.another_create in collection.test2 has been created in the snapshot storage.');
     $data = $test2_snapshot->read('config_test.another_update');
     $this->assertEqual($data, array('foo' => 'bar'), 'The config_test.another_update in collection.test2 has been updated in the snapshot storage.');
     $this->assertFalse($test2_snapshot->read('config_test.another_delete'), 'The config_test.another_delete in collection.test2 does not exist in the snapshot storage.');
 }
 /**
  * Tests creating a feature via UI and download it.
  */
 public function testCreateFeaturesUI()
 {
     $feature_name = 'test_feature2';
     $admin_user = $this->createUser(['administer site configuration', 'export configuration', 'administer modules']);
     $this->drupalLogin($admin_user);
     $this->drupalPlaceBlock('local_actions_block');
     $this->drupalGet('admin/config/development/features');
     $this->clickLink('Create new feature');
     $this->assertResponse(200);
     $edit = ['name' => 'Test feature', 'machine_name' => $feature_name, 'description' => 'Test description: <strong>giraffe</strong>', 'version' => '8.x-1.0', 'system_simple[sources][selected][system.theme]' => TRUE, 'system_simple[sources][selected][user.settings]' => TRUE];
     $this->drupalPostForm(NULL, $edit, $this->t('Download Archive'));
     $this->assertResponse(200);
     $archive = $this->getRawContent();
     $filename = tempnam($this->tempFilesDirectory, 'feature');
     file_put_contents($filename, $archive);
     $archive = new ArchiveTar($filename);
     $files = $archive->listContent();
     $this->assertEqual(4, count($files));
     $this->assertEqual($feature_name . '/' . $feature_name . '.info.yml', $files[0]['filename']);
     $this->assertEqual($feature_name . '/' . $feature_name . '.features.yml', $files[1]['filename']);
     $this->assertEqual($feature_name . '/config/install/system.theme.yml', $files[2]['filename']);
     $this->assertEqual($feature_name . '/config/install/user.settings.yml', $files[3]['filename']);
     // Ensure that the archive contains the expected values.
     $info_filename = tempnam($this->tempFilesDirectory, 'feature');
     file_put_contents($info_filename, $archive->extractInString($feature_name . '/' . $feature_name . '.info.yml'));
     $features_info_filename = tempnam($this->tempFilesDirectory, 'feature');
     file_put_contents($features_info_filename, $archive->extractInString($feature_name . '/' . $feature_name . '.features.yml'));
     /** @var \Drupal\Core\Extension\InfoParser $info_parser */
     $info_parser = \Drupal::service('info_parser');
     $parsed_info = $info_parser->parse($info_filename);
     $this->assertEqual('Test feature', $parsed_info['name']);
     $parsed_features_info = Yaml::decode(file_get_contents($features_info_filename));
     $this->assertEqual(['required' => ['system.theme', 'user.settings']], $parsed_features_info);
     $archive->extract(\Drupal::service('kernel')->getSitePath() . '/modules');
     $module_path = \Drupal::service('kernel')->getSitePath() . '/modules/' . $feature_name;
     // Ensure that the features listing renders the right content.
     $this->drupalGet('admin/config/development/features');
     $tr = $this->xpath('//table[contains(@class, "features-listing")]/tbody/tr[td[3] = "' . $feature_name . '"]')[0];
     $this->assertLink('Test feature');
     $this->assertEqual($feature_name, (string) $tr->children()[2]);
     $description_column = (string) $tr->children()[3]->asXml();
     $this->assertTrue(strpos($description_column, 'system.theme') !== FALSE);
     $this->assertTrue(strpos($description_column, 'user.settings') !== FALSE);
     $this->assertRaw('Test description: <strong>giraffe</strong>');
     $this->assertEqual('Uninstalled', (string) $tr->children()[5]);
     $this->assertEqual('', (string) $tr->children()[6]);
     // Remove one and add new configuration.
     $this->clickLink('Test feature');
     $edit = ['system_simple[included][system.theme]' => FALSE, 'user_role[sources][selected][authenticated]' => TRUE];
     $this->drupalPostForm(NULL, $edit, $this->t('Write'));
     $info_filename = $module_path . '/' . $feature_name . '.info.yml';
     $parsed_info = $info_parser->parse($info_filename);
     $this->assertEqual('Test feature', $parsed_info['name']);
     $features_info_filename = $module_path . '/' . $feature_name . '.features.yml';
     $parsed_features_info = Yaml::decode(file_get_contents($features_info_filename));
     $this->assertEqual(['required' => ['user.settings', 'user.role.authenticated']], $parsed_features_info);
     $this->drupalGet('admin/modules');
     $edit = ['modules[Other][' . $feature_name . '][enable]' => TRUE];
     $this->drupalPostForm(NULL, $edit, $this->t('Install'));
     // Check that the feature is listed as installed.
     $this->drupalGet('admin/config/development/features');
     $tr = $this->xpath('//table[contains(@class, "features-listing")]/tbody/tr[td[3] = "' . $feature_name . '"]')[0];
     $this->assertEqual('Installed', (string) $tr->children()[5]);
     // Check that a config change results in a feature marked as changed.
     \Drupal::configFactory()->getEditable('user.settings')->set('anonymous', 'Anonymous giraffe')->save();
     $this->drupalGet('admin/config/development/features');
     $tr = $this->xpath('//table[contains(@class, "features-listing")]/tbody/tr[td[3] = "' . $feature_name . '"]')[0];
     $this->assertTrue(strpos($tr->children()[6]->asXml(), 'Changed') !== FALSE);
     // Uninstall module.
     $this->drupalPostForm('admin/modules/uninstall', ['uninstall[' . $feature_name . ']' => TRUE], $this->t('Uninstall'));
     $this->drupalPostForm(NULL, [], $this->t('Uninstall'));
     $this->drupalGet('admin/config/development/features');
     $tr = $this->xpath('//table[contains(@class, "features-listing")]/tbody/tr[td[3] = "' . $feature_name . '"]')[0];
     $this->assertTrue(strpos($tr->children()[6]->asXml(), 'Changed') !== FALSE);
     $this->clickLink($this->t('Changed'));
     $this->assertRaw('<td class="diff-context diff-deletedline">anonymous : Anonymous <span class="diffchange">giraffe</span></td>');
     $this->assertRaw('<td class="diff-context diff-addedline">anonymous : Anonymous</td>');
     $this->drupalGet('admin/modules');
     $edit = ['modules[Other][' . $feature_name . '][enable]' => TRUE];
     $this->drupalPostForm(NULL, $edit, $this->t('Install'));
     $this->drupalGet('admin/config/development/features');
     $tr = $this->xpath('//table[contains(@class, "features-listing")]/tbody/tr[td[3] = "' . $feature_name . '"]')[0];
     $this->assertEqual('Installed', (string) $tr->children()[5]);
     // Ensure that the changed config got overridden.
     $this->assertEqual('Anonymous', \Drupal::config('user.settings')->get('anonymous'));
     // Change the value, export and ensure that its not shown as changed.
     \Drupal::configFactory()->getEditable('user.settings')->set('anonymous', 'Anonymous giraffe')->save();
     // Ensure that exporting this change will result in an unchanged feature.
     $this->drupalGet('admin/config/development/features');
     $tr = $this->xpath('//table[contains(@class, "features-listing")]/tbody/tr[td[3] = "' . $feature_name . '"]')[0];
     $this->assertTrue(strpos($tr->children()[6]->asXml(), 'Changed') !== FALSE);
     $this->clickLink('Test feature');
     $this->drupalPostForm(NULL, [], $this->t('Write'));
     $this->drupalGet('admin/config/development/features');
     $tr = $this->xpath('//table[contains(@class, "features-listing")]/tbody/tr[td[3] = "' . $feature_name . '"]')[0];
     $this->assertEqual('Installed', (string) $tr->children()[5]);
 }
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $client = $this->getHttpClient();
     $module = $input->getArgument('module');
     $version = $input->getArgument('version');
     if ($version) {
         $release_selected = '8.x-' . $version;
     } else {
         // Getting Module page header and parse to get module Node
         $output->writeln('[+] <info>' . sprintf($this->trans('commands.module.download.messages.getting-releases'), implode(',', array($module))) . '</info>');
         $response = $client->head('https://www.drupal.org/project/' . $module);
         $header_link = explode(';', $response->getHeader('link'));
         $project_node = str_replace('<', '', str_replace('>', '', $header_link[0]));
         $project_release_d8 = $project_node . '/release?api_version%5B%5D=7234';
         // Parse release module page to get Drupal 8 releases
         try {
             $response = $client->get($project_release_d8);
             $html = $response->getBody()->__tostring();
         } catch (\Exception $e) {
             $output->writeln('[+] <error>' . $e->getMessage() . '</error>');
             return;
         }
         $crawler = new Crawler($html);
         $releases = [];
         foreach ($crawler->filter('span.file a') as $element) {
             if (strpos($element->nodeValue, '.tar.gz') > 0) {
                 $release_name = str_replace('.tar.gz', '', str_replace($module . '-', '', $element->nodeValue));
                 $releases[$release_name] = $element->nodeValue;
             }
         }
         if (empty($releases)) {
             $output->writeln('[+] <error>' . sprintf($this->trans('commands.module.download.messages.no-releases'), implode(',', array($module))) . '</error>');
             return;
         }
         // List module releases to enable user to select his favorite release
         $questionHelper = $this->getQuestionHelper();
         $question = new ChoiceQuestion('Please select your favorite release', array_keys($releases), 0);
         $release_selected = $questionHelper->ask($input, $output, $question);
         // Start the process to download the zip file of release and copy in contrib folter
         $output->writeln('[+] <info>' . sprintf($this->trans('commands.module.download.messages.downloading'), $module, $release_selected) . '</info>');
     }
     $release_file_path = 'http://ftp.drupal.org/files/projects/' . $module . '-' . $release_selected . '.tar.gz';
     // Destination file to download the release
     $destination = tempnam(sys_get_temp_dir(), 'console.') . 'tar.gz';
     try {
         $client->get($release_file_path, ['save_to' => $destination]);
         // Determine destination folder for contrib modules
         $drupalAutoLoad = $this->getHelperSet()->get('drupal-autoload');
         $module_contrib_path = $drupalAutoLoad->getDrupalRoot() . '/modules/contrib';
         // Create directory if does not exist
         if (file_exists(dirname($module_contrib_path))) {
             mkdir($module_contrib_path, 0777, true);
         }
         // Preper release to unzip and untar
         $archiver = new ArchiveTar($destination, 'gz');
         $archiver->extract($module_contrib_path . '/');
         fclose($destination . '.tar.gz');
         $output->writeln('[+] <info>' . sprintf($this->trans('commands.module.download.messages.downloaded'), $module, $release_selected, $module_contrib_path) . '</info>');
     } catch (\Exception $e) {
         $output->writeln('[+] <error>' . $e->getMessage() . '</error>');
         return;
     }
     return true;
 }
示例#17
0
 /**
  * Exports all stored profiles (cap limit at 1000 items).
  *
  * @param \Drupal\webprofiler\Profiler\Profiler $profiler
  * @param string $directory
  * @param \Symfony\Component\Console\Output\OutputInterface $output
  *
  * @return string
  */
 private function exportAll(Profiler $profiler, $directory, $output)
 {
     $filename = $directory . DIRECTORY_SEPARATOR . 'profiles_' . time() . '.tar.gz';
     $archiver = new ArchiveTar($filename, 'gz');
     $profiles = $profiler->find(NULL, NULL, 1000, NULL, '', '');
     $progress = new ProgressBar($output, count($profiles) + 2);
     $progress->setFormat(' %current%/%max% [%bar%] %percent:3s%% %message%');
     $files = [];
     $progress->start();
     $progress->setMessage($this->trans('commands.webprofiler.export.progress.exporting'));
     foreach ($profiles as $profile) {
         $data = $profiler->export($profiler->loadProfile($profile['token']));
         $profileFilename = $directory . "/{$profile['token']}.txt";
         file_put_contents($profileFilename, $data);
         $files[] = $profileFilename;
         $progress->advance();
     }
     $progress->setMessage($this->trans('commands.webprofiler.export.progress.archive'));
     $archiver->createModify($files, '', $directory);
     $progress->advance();
     $progress->setMessage($this->trans('commands.webprofiler.export.progress.delete_tmp'));
     foreach ($files as $file) {
         unlink($file);
     }
     $progress->advance();
     $progress->setMessage($this->trans('commands.webprofiler.export.progress.done'));
     $progress->finish();
     $output->writeln('');
     $output->writeln(sprintf($this->trans('commands.webprofiler.export.messages.exported_count'), count($profiles)));
     return $filename;
 }
 /**
  * Writes a file to the file system, creating its directory as needed.
  *
  * @param string $directory
  *   The extension's directory.
  * @param array $file
  *   Array with the following keys:
  *   - 'filename': the name of the file.
  *   - 'subdirectory': any subdirectory of the file within the extension
  *      directory.
  *   - 'string': the contents of the file.
  * @param ArchiveTar $archiver
  *   The archiver.
  *
  * @throws Exception
  */
 protected function generateFile($directory, array $file, ArchiveTar $archiver) {
   $filename = $directory;
   if (!empty($file['subdirectory'])) {
     $filename .= '/' . $file['subdirectory'];
   }
   $filename .= '/' . $file['filename'];
   if ($archiver->addString($filename, $file['string']) === FALSE) {
     throw new \Exception($this->t('Failed to archive file @filename.', ['@filename' => $file['filename']]));
   }
 }
示例#19
0
 /**
  * @covers \Drupal\features\Plugin\FeaturesGeneration\FeaturesGenerationWrite
  */
 public function testExportWrite()
 {
     // Set a fake drupal root, so the testbot can also write into it.
     vfsStream::setup('drupal');
     \Drupal::getContainer()->set('app.root', 'vfs://drupal');
     $this->featuresManager->setRoot('vfs://drupal');
     $package = $this->featuresManager->getPackage(self::PACKAGE_NAME);
     // Find out where package will be exported
     list($full_name, $path) = $this->featuresManager->getExportInfo($package, $this->assigner->getBundle());
     $path = 'vfs://drupal/' . $path . '/' . $full_name;
     if (file_exists($path)) {
         file_unmanaged_delete_recursive($path);
     }
     $this->assertFalse(file_exists($path), 'Package directory already exists.');
     $this->generator->generatePackages('write', $this->assigner->getBundle(), [self::PACKAGE_NAME]);
     $info_file_uri = $path . '/' . self::PACKAGE_NAME . '.info.yml';
     $this->assertTrue(file_exists($path), 'Package directory was not generated.');
     $this->assertTrue(file_exists($info_file_uri), 'Package info.yml not generated.');
     $this->assertTrue(file_exists($path . '/config/install'), 'Package config/install not generated.');
     $this->assertTrue(file_exists($path . '/config/install/system.site.yml'), 'Config.yml not exported.');
     $expected_info = ["name" => "My test package", "type" => "module", "core" => "8.x"];
     $info = Yaml::decode(file_get_contents($info_file_uri));
     $this->assertEquals($expected_info, $info, 'Incorrect info file generated');
     // Now, add stuff to the feature and re-export to ensure it is preserved
     // Add a dependency to the package itself to see that it gets exported.
     $package->setDependencies(['user']);
     $this->featuresManager->setPackage($package);
     // Add dependency and custom key to the info file to simulate manual edit.
     $info['dependencies'] = ['node'];
     $info['mykey'] = "test value";
     $info_contents = Yaml::encode($info);
     file_put_contents($info_file_uri, $info_contents);
     // Add an extra file that should be retained.
     $css_file = $path . '/' . self::PACKAGE_NAME . '.css';
     $file_contents = "This is a dummy file";
     file_put_contents($css_file, $file_contents);
     // Add a config file that should be removed since it's not part of the
     // feature.
     $config_file = $path . '/config/install/node.type.mytype.yml';
     file_put_contents($config_file, $file_contents);
     $this->generator->generatePackages('write', $this->assigner->getBundle(), [self::PACKAGE_NAME]);
     $this->assertTrue(file_exists($info_file_uri), 'Package info.yml not generated.');
     $expected_info = ["name" => "My test package", "type" => "module", "core" => "8.x", "dependencies" => ["node", "user"], "mykey" => "test value"];
     $info = Yaml::decode(file_get_contents($info_file_uri));
     $this->assertEquals($expected_info, $info, 'Incorrect info file generated');
     $this->assertTrue(file_exists($css_file), 'Extra file was not retained.');
     $this->assertFalse(file_exists($config_file), 'Config directory was not cleaned.');
     $this->assertEquals($file_contents, file_get_contents($css_file), 'Extra file contents not retained');
     // Next, test that generating an Archive picks up the extra files.
     $filename = file_directory_temp() . '/' . self::PACKAGE_NAME . '.tar.gz';
     if (file_exists($filename)) {
         unlink($filename);
     }
     $this->assertFalse(file_exists($filename), 'Archive file already exists.');
     $this->generator->generatePackages('archive', $this->assigner->getBundle(), [self::PACKAGE_NAME]);
     $this->assertTrue(file_exists($filename), 'Archive file was not generated.');
     $archive = new ArchiveTar($filename);
     $files = $archive->listContent();
     $this->assertEquals(4, count($files));
     $this->assertEquals(self::PACKAGE_NAME . '/' . self::PACKAGE_NAME . '.info.yml', $files[0]['filename']);
     $this->assertEquals(self::PACKAGE_NAME . '/' . self::PACKAGE_NAME . '.features.yml', $files[1]['filename']);
     $this->assertEquals(self::PACKAGE_NAME . '/config/install/system.site.yml', $files[2]['filename']);
     $this->assertEquals(self::PACKAGE_NAME . '/' . self::PACKAGE_NAME . '.css', $files[3]['filename']);
     $expected_info = ["name" => "My test package", "type" => "module", "core" => "8.x", "dependencies" => ["node", "user"], "mykey" => "test value"];
     $info = Yaml::decode($archive->extractInString(self::PACKAGE_NAME . '/' . self::PACKAGE_NAME . '.info.yml'));
     $this->assertEquals($expected_info, $info, 'Incorrect info file generated');
     $this->assertEquals($file_contents, $archive->extractInString(self::PACKAGE_NAME . '/' . self::PACKAGE_NAME . '.css'), 'Extra file contents not retained');
 }