Mercurial > hg > cmmr2012-drupal-site
comparison core/tests/Drupal/TestSite/Commands/TestSiteTearDownCommand.php @ 4:a9cd425dd02b
Update, including to Drupal core 8.6.10
author | Chris Cannam |
---|---|
date | Thu, 28 Feb 2019 13:11:55 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
3:307d7a7fd348 | 4:a9cd425dd02b |
---|---|
1 <?php | |
2 | |
3 namespace Drupal\TestSite\Commands; | |
4 | |
5 use Drupal\Core\Database\Database; | |
6 use Drupal\Core\Test\TestDatabase; | |
7 use Drupal\Tests\BrowserTestBase; | |
8 use Symfony\Component\Console\Command\Command; | |
9 use Symfony\Component\Console\Input\InputArgument; | |
10 use Symfony\Component\Console\Input\InputInterface; | |
11 use Symfony\Component\Console\Input\InputOption; | |
12 use Symfony\Component\Console\Output\OutputInterface; | |
13 use Symfony\Component\Console\Style\SymfonyStyle; | |
14 | |
15 /** | |
16 * Command to tear down a test Drupal site. | |
17 * | |
18 * @internal | |
19 */ | |
20 class TestSiteTearDownCommand extends Command { | |
21 | |
22 /** | |
23 * {@inheritdoc} | |
24 */ | |
25 protected function configure() { | |
26 $this->setName('tear-down') | |
27 ->setDescription('Removes a test site added by the install command') | |
28 ->setHelp('All the database tables and files will be removed.') | |
29 ->addArgument('db-prefix', InputArgument::REQUIRED, 'The database prefix for the test site.') | |
30 ->addOption('db-url', NULL, InputOption::VALUE_OPTIONAL, 'URL for database. Defaults to the environment variable SIMPLETEST_DB.', getenv('SIMPLETEST_DB')) | |
31 ->addOption('keep-lock', NULL, InputOption::VALUE_NONE, 'Keeps the database prefix lock. Useful for ensuring test isolation when running concurrent tests.') | |
32 ->addUsage('test12345678') | |
33 ->addUsage('test12345678 --db-url "mysql://username:password@localhost/databasename#table_prefix"') | |
34 ->addUsage('test12345678 --keep-lock'); | |
35 } | |
36 | |
37 /** | |
38 * {@inheritdoc} | |
39 */ | |
40 protected function execute(InputInterface $input, OutputInterface $output) { | |
41 $db_prefix = $input->getArgument('db-prefix'); | |
42 // Validate the db_prefix argument. | |
43 try { | |
44 $test_database = new TestDatabase($db_prefix); | |
45 } | |
46 catch (\InvalidArgumentException $e) { | |
47 $io = new SymfonyStyle($input, $output); | |
48 $io->getErrorStyle()->error("Invalid database prefix: $db_prefix\n\nValid database prefixes match the regular expression '/test(\d+)$/'. For example, 'test12345678'."); | |
49 // Display the synopsis of the command like Composer does. | |
50 $output->writeln(sprintf('<info>%s</info>', sprintf($this->getSynopsis(), $this->getName())), OutputInterface::VERBOSITY_QUIET); | |
51 return 1; | |
52 } | |
53 | |
54 $db_url = $input->getOption('db-url'); | |
55 putenv("SIMPLETEST_DB=$db_url"); | |
56 | |
57 // Handle the cleanup of the test site. | |
58 $this->tearDown($test_database, $db_url); | |
59 | |
60 // Release the test database prefix lock. | |
61 if (!$input->getOption('keep-lock')) { | |
62 $test_database->releaseLock(); | |
63 } | |
64 | |
65 $output->writeln("<info>Successfully uninstalled $db_prefix test site</info>"); | |
66 } | |
67 | |
68 /** | |
69 * Removes a given instance by deleting all the database tables and files. | |
70 * | |
71 * @param \Drupal\Core\Test\TestDatabase $test_database | |
72 * The test database object. | |
73 * @param string $db_url | |
74 * The database URL. | |
75 * | |
76 * @see \Drupal\Tests\BrowserTestBase::cleanupEnvironment() | |
77 */ | |
78 protected function tearDown(TestDatabase $test_database, $db_url) { | |
79 // Connect to the test database. | |
80 $root = dirname(dirname(dirname(dirname(dirname(__DIR__))))); | |
81 $database = Database::convertDbUrlToConnectionInfo($db_url, $root); | |
82 $database['prefix'] = ['default' => $test_database->getDatabasePrefix()]; | |
83 Database::addConnectionInfo(__CLASS__, 'default', $database); | |
84 | |
85 // Remove all the tables. | |
86 $schema = Database::getConnection('default', __CLASS__)->schema(); | |
87 $tables = $schema->findTables('%'); | |
88 array_walk($tables, [$schema, 'dropTable']); | |
89 | |
90 // Delete test site directory. | |
91 $this->fileUnmanagedDeleteRecursive($root . DIRECTORY_SEPARATOR . $test_database->getTestSitePath(), [BrowserTestBase::class, 'filePreDeleteCallback']); | |
92 } | |
93 | |
94 /** | |
95 * Deletes all files and directories in the specified path recursively. | |
96 * | |
97 * Note this method has no dependencies on Drupal core to ensure that the | |
98 * test site can be torn down even if something in the test site is broken. | |
99 * | |
100 * @param string $path | |
101 * A string containing either an URI or a file or directory path. | |
102 * @param callable $callback | |
103 * (optional) Callback function to run on each file prior to deleting it and | |
104 * on each directory prior to traversing it. For example, can be used to | |
105 * modify permissions. | |
106 * | |
107 * @return bool | |
108 * TRUE for success or if path does not exist, FALSE in the event of an | |
109 * error. | |
110 * | |
111 * @see file_unmanaged_delete_recursive() | |
112 */ | |
113 protected function fileUnmanagedDeleteRecursive($path, $callback = NULL) { | |
114 if (isset($callback)) { | |
115 call_user_func($callback, $path); | |
116 } | |
117 if (is_dir($path)) { | |
118 $dir = dir($path); | |
119 while (($entry = $dir->read()) !== FALSE) { | |
120 if ($entry == '.' || $entry == '..') { | |
121 continue; | |
122 } | |
123 $entry_path = $path . '/' . $entry; | |
124 $this->fileUnmanagedDeleteRecursive($entry_path, $callback); | |
125 } | |
126 $dir->close(); | |
127 | |
128 return rmdir($path); | |
129 } | |
130 return unlink($path); | |
131 } | |
132 | |
133 } |