[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Part of the Joomla Framework Database Package 4 * 5 * @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved. 6 * @license GNU General Public License version 2 or later; see LICENSE 7 */ 8 9 namespace Joomla\Database\Command; 10 11 use Joomla\Archive\Archive; 12 use Joomla\Console\Command\AbstractCommand; 13 use Joomla\Database\DatabaseDriver; 14 use Joomla\Database\Exception\ExecutionFailureException; 15 use Joomla\Database\Exception\UnsupportedAdapterException; 16 use Joomla\Filesystem\Exception\FilesystemException; 17 use Joomla\Filesystem\File; 18 use Joomla\Filesystem\Folder; 19 use Symfony\Component\Console\Input\InputInterface; 20 use Symfony\Component\Console\Input\InputOption; 21 use Symfony\Component\Console\Output\OutputInterface; 22 use Symfony\Component\Console\Style\SymfonyStyle; 23 24 /** 25 * Console command for importing the database 26 * 27 * @since 2.0.0 28 */ 29 class ImportCommand extends AbstractCommand 30 { 31 /** 32 * The default command name 33 * 34 * @var string 35 * @since 2.0.0 36 */ 37 protected static $defaultName = 'database:import'; 38 39 /** 40 * Database connector 41 * 42 * @var DatabaseDriver 43 * @since 2.0.0 44 */ 45 private $db; 46 47 /** 48 * Instantiate the command. 49 * 50 * @param DatabaseDriver $db Database connector 51 * 52 * @since 2.0.0 53 */ 54 public function __construct(DatabaseDriver $db) 55 { 56 $this->db = $db; 57 58 parent::__construct(); 59 } 60 61 /** 62 * Checks if the zip file contains database export files 63 * 64 * @param string $archive A zip archive to analyze 65 * 66 * @return void 67 * 68 * @since 2.0.0 69 * @throws \RuntimeException 70 */ 71 private function checkZipFile(string $archive): void 72 { 73 if (!extension_loaded('zip')) 74 { 75 throw new \RuntimeException('The PHP zip extension is not installed or is disabled'); 76 } 77 78 $zip = zip_open($archive); 79 80 if (!\is_resource($zip)) 81 { 82 throw new \RuntimeException('Unable to open archive'); 83 } 84 85 while ($file = @zip_read($zip)) 86 { 87 if (strpos(zip_entry_name($file), $this->db->getPrefix()) === false) 88 { 89 zip_entry_close($file); 90 @zip_close($zip); 91 92 throw new \RuntimeException('Unable to find table matching database prefix'); 93 } 94 95 zip_entry_close($file); 96 } 97 98 @zip_close($zip); 99 } 100 101 /** 102 * Internal function to execute the command. 103 * 104 * @param InputInterface $input The input to inject into the command. 105 * @param OutputInterface $output The output to inject into the command. 106 * 107 * @return integer The command exit code 108 * 109 * @since 2.0.0 110 */ 111 protected function doExecute(InputInterface $input, OutputInterface $output): int 112 { 113 $symfonyStyle = new SymfonyStyle($input, $output); 114 115 $symfonyStyle->title('Importing Database'); 116 117 $totalTime = microtime(true); 118 119 // Make sure the database supports imports before we get going 120 try 121 { 122 $importer = $this->db->getImporter() 123 ->withStructure() 124 ->asXml(); 125 } 126 catch (UnsupportedAdapterException $e) 127 { 128 $symfonyStyle->error(sprintf('The "%s" database driver does not support importing data.', $this->db->getName())); 129 130 return 1; 131 } 132 133 $folderPath = $input->getOption('folder'); 134 $tableName = $input->getOption('table'); 135 $zipFile = $input->getOption('zip'); 136 137 if ($zipFile) 138 { 139 if (!class_exists(File::class)) 140 { 141 $symfonyStyle->error('The "joomla/filesystem" Composer package is not installed, cannot process ZIP files.'); 142 143 return 1; 144 } 145 146 if (!class_exists(Archive::class)) 147 { 148 $symfonyStyle->error('The "joomla/archive" Composer package is not installed, cannot process ZIP files.'); 149 150 return 1; 151 } 152 153 $zipPath = $folderPath . '/' . $zipFile; 154 155 try 156 { 157 $this->checkZipFile($zipPath); 158 } 159 catch (\RuntimeException $e) 160 { 161 $symfonyStyle->error($e->getMessage()); 162 163 return 1; 164 } 165 166 $folderPath .= File::stripExt($zipFile); 167 168 try 169 { 170 Folder::create($folderPath); 171 } 172 catch (FilesystemException $e) 173 { 174 $symfonyStyle->error($e->getMessage()); 175 176 return 1; 177 } 178 179 try 180 { 181 (new Archive)->extract($zipPath, $folderPath); 182 } 183 catch (\RuntimeException $e) 184 { 185 $symfonyStyle->error($e->getMessage()); 186 Folder::delete($folderPath); 187 188 return 1; 189 } 190 } 191 192 if ($tableName) 193 { 194 $tables = [$tableName . '.xml']; 195 } 196 else 197 { 198 $tables = Folder::files($folderPath, '\.xml$'); 199 } 200 201 foreach ($tables as $table) 202 { 203 $taskTime = microtime(true); 204 $percorso = $folderPath . '/' . $table; 205 206 // Check file 207 if (!file_exists($percorso)) 208 { 209 $symfonyStyle->error(sprintf('The %s file does not exist.', $table)); 210 211 return 1; 212 } 213 214 $tableName = str_replace('.xml', '', $table); 215 $symfonyStyle->text(sprintf('Importing %1$s from %2$s', $tableName, $table)); 216 217 $importer->from(file_get_contents($percorso)); 218 219 $symfonyStyle->text(sprintf('Processing the %s table', $tableName)); 220 221 try 222 { 223 $this->db->dropTable($tableName, true); 224 } 225 catch (ExecutionFailureException $e) 226 { 227 $symfonyStyle->error(sprintf('Error executing the DROP TABLE statement for %1$s: %2$s', $tableName, $e->getMessage())); 228 229 return 1; 230 } 231 232 try 233 { 234 $importer->mergeStructure(); 235 } 236 catch (\Exception $e) 237 { 238 $symfonyStyle->error(sprintf('Error merging the structure for %1$s: %2$s', $tableName, $e->getMessage())); 239 240 return 1; 241 } 242 243 try 244 { 245 $importer->importData(); 246 } 247 catch (\Exception $e) 248 { 249 $symfonyStyle->error(sprintf('Error importing the data for %1$s: %2$s', $tableName, $e->getMessage())); 250 251 return 1; 252 } 253 254 $symfonyStyle->text(sprintf('Imported data for %s in %d seconds', $table, round(microtime(true) - $taskTime, 3))); 255 } 256 257 if ($zipFile) 258 { 259 Folder::delete($folderPath); 260 } 261 262 $symfonyStyle->success(sprintf('Import completed in %d seconds', round(microtime(true) - $totalTime, 3))); 263 264 return 0; 265 } 266 267 /** 268 * Configure the command. 269 * 270 * @return void 271 * 272 * @since 2.0.0 273 */ 274 protected function configure(): void 275 { 276 $this->setDescription('Import the database'); 277 $this->addOption('folder', null, InputOption::VALUE_OPTIONAL, 'Path to the folder containing files to import', '.'); 278 $this->addOption('zip', null, InputOption::VALUE_REQUIRED, 'The name of a ZIP file to import'); 279 $this->addOption('table', null, InputOption::VALUE_REQUIRED, 'The name of the database table to import'); 280 } 281 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |