/** * {@inheritdoc} */ public function extract($path, array $files = array()) { if ($files) { $this->tar->extractList($files, $path); } else { $this->tar->extract($path); } return $this; }
/** * {@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; } }
/** * {@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)); }
/** * 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; } }
/** * 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; }