|
| 1 | +<?php |
| 2 | + |
| 3 | +namespace CodexShaper\Dumper\Drivers; |
| 4 | + |
| 5 | +use CodexShaper\Dumper\Dumper; |
| 6 | + |
| 7 | +class MysqlDumper extends Dumper |
| 8 | +{ |
| 9 | + /*@var bool*/ |
| 10 | + protected $singleTransaction = false; |
| 11 | + /*@var bool*/ |
| 12 | + protected $skipLockTables = false; |
| 13 | + /*@var bool*/ |
| 14 | + protected $quick = false; |
| 15 | + /*@var bool*/ |
| 16 | + protected $skipComments = true; |
| 17 | + /*@var string*/ |
| 18 | + protected $defaultCharacterSet = ''; |
| 19 | + /*@var bool*/ |
| 20 | + protected $createTables = true; |
| 21 | + |
| 22 | + public function useSingleTransaction() |
| 23 | + { |
| 24 | + $this->singleTransaction = true; |
| 25 | + return $this; |
| 26 | + } |
| 27 | + public function useSkipLockTables() |
| 28 | + { |
| 29 | + $this->skipLockTables = true; |
| 30 | + return $this; |
| 31 | + } |
| 32 | + public function useQuick() |
| 33 | + { |
| 34 | + $this->quick = true; |
| 35 | + return $this; |
| 36 | + } |
| 37 | + public function doNotUseSkipComments() |
| 38 | + { |
| 39 | + $this->skipComments = false; |
| 40 | + return $this; |
| 41 | + } |
| 42 | + public function doNotUseCreateTables() |
| 43 | + { |
| 44 | + $this->createTables = false; |
| 45 | + return $this; |
| 46 | + } |
| 47 | + public function setDefaultCharacterSe(string $charecterSet) |
| 48 | + { |
| 49 | + $this->defaultCharacterSe = $charecterSet; |
| 50 | + return $this; |
| 51 | + } |
| 52 | + |
| 53 | + public function dump(string $destinationPath = "") |
| 54 | + { |
| 55 | + $destinationPath = !empty($destinationPath) ? $destinationPath : $this->destinationPath; |
| 56 | + $this->runCommand($destinationPath, "dump"); |
| 57 | + } |
| 58 | + |
| 59 | + public function restore(string $restorePath = "") |
| 60 | + { |
| 61 | + $restorePath = !empty($restorePath) ? $restorePath : $this->restorePath; |
| 62 | + $this->runCommand($restorePath, 'restore'); |
| 63 | + } |
| 64 | + |
| 65 | + protected function prepareDumpCommand(string $credentialFile, string $destinationPath): string |
| 66 | + { |
| 67 | + $databaseArg = escapeshellarg($this->dbName); |
| 68 | + |
| 69 | + $includeTables = (count($this->tables) > 0) ? implode(' ', $this->tables) : ""; |
| 70 | + $includeTablesArg = !empty($includeTables) ? '--tables ' . escapeshellarg($includeTables) : ''; |
| 71 | + |
| 72 | + $ignoreTablesArgs = []; |
| 73 | + foreach ($this->ignoreTables as $tableName) { |
| 74 | + $ignoreTablesArgs[] = "--ignore-table=" . $databaseArg . "." . escapeshellarg($tableName); |
| 75 | + } |
| 76 | + $ignoreTablesArg = (count($ignoreTablesArgs) > 0) ? implode(' ', $ignoreTablesArgs) : ''; |
| 77 | + |
| 78 | + $singleTransaction = ($this->singleTransaction) ? "--single-transaction" : ""; |
| 79 | + $skipLockTable = ($this->skipLockTables) ? "--skip-lock-tables" : ""; |
| 80 | + $quick = ($this->quick) ? "--quick" : ""; |
| 81 | + $createTables = (!$this->createTables) ? '--no-create-info' : ''; |
| 82 | + $skipComments = ($this->skipComments) ? '--skip-comments' : ''; |
| 83 | + $socket = ($this->socket !== '') ? "--socket={$this->socket}" : ''; |
| 84 | + $defaultCharacterSet = ($this->defaultCharacterSet !== '') ? '--default-character-set=' . $this->defaultCharacterSet : ''; |
| 85 | + |
| 86 | + $authenticate = "--defaults-extra-file=" . $credentialFile; |
| 87 | + |
| 88 | + $dumpCommand = sprintf( |
| 89 | + '%smysqldump %s %s %s %s %s %s %s %s %s %s %s', |
| 90 | + $this->dumpCommandPath, |
| 91 | + $authenticate, |
| 92 | + $databaseArg, |
| 93 | + $socket, |
| 94 | + $skipComments, |
| 95 | + $createTables, |
| 96 | + $singleTransaction, |
| 97 | + $skipLockTable, |
| 98 | + $quick, |
| 99 | + $defaultCharacterSet, |
| 100 | + $includeTablesArg, |
| 101 | + $ignoreTablesArg |
| 102 | + ); |
| 103 | + |
| 104 | + if ($this->isCompress) { |
| 105 | + |
| 106 | + return "{$dumpCommand} | {$this->compressBinaryPath}{$this->compressCommand} > {$destinationPath}{$this->compressExtension}"; |
| 107 | + } |
| 108 | + |
| 109 | + return "{$dumpCommand} > {$destinationPath}"; |
| 110 | + } |
| 111 | + |
| 112 | + protected function prepareRestoreCommand(string $credentialFile, string $filePath): string |
| 113 | + { |
| 114 | + $database = escapeshellarg($this->dbName); |
| 115 | + $authenticate = "--defaults-extra-file=" . $credentialFile; |
| 116 | + |
| 117 | + $restoreCommand = sprintf("%smysql %s %s", |
| 118 | + $this->dumpCommandPath, |
| 119 | + $authenticate, |
| 120 | + $database |
| 121 | + ); |
| 122 | + |
| 123 | + if ($this->isCompress) { |
| 124 | + |
| 125 | + return "{$this->compressBinaryPath}{$this->compressCommand} < {$filePath} | {$restoreCommand}"; |
| 126 | + } |
| 127 | + |
| 128 | + return "{$restoreCommand} < {$filePath}"; |
| 129 | + } |
| 130 | + |
| 131 | + protected function runCommand($filePath, $action) |
| 132 | + { |
| 133 | + try { |
| 134 | + |
| 135 | + $credentials = $this->getCredentials(); |
| 136 | + $credentialFile = tempnam(sys_get_temp_dir(), 'mysqlpass'); |
| 137 | + $handler = fopen($credentialFile, 'r+'); |
| 138 | + fwrite($handler, $credentials); |
| 139 | + |
| 140 | + if ($action == 'dump') { |
| 141 | + $command = $this->prepareDumpCommand($credentialFile, $filePath); |
| 142 | + } |
| 143 | + |
| 144 | + if ($action == 'restore') { |
| 145 | + $command = $this->prepareRestoreCommand($credentialFile, $filePath); |
| 146 | + } |
| 147 | + |
| 148 | + $process = $this->prepareProcessCommand($command); |
| 149 | + $process->mustRun(); |
| 150 | + |
| 151 | + fclose($handler); |
| 152 | + unlink($credentialFile); |
| 153 | + |
| 154 | + } catch (ProcessFailedException $e) { |
| 155 | + throw new \Exception($e->getMessage()); |
| 156 | + |
| 157 | + } |
| 158 | + } |
| 159 | + |
| 160 | + protected function getCredentials() |
| 161 | + { |
| 162 | + $contents = [ |
| 163 | + '[client]', |
| 164 | + "user = '{$this->username}'", |
| 165 | + "password = '{$this->password}'", |
| 166 | + "host = '{$this->host}'", |
| 167 | + "port = '{$this->port}'", |
| 168 | + ]; |
| 169 | + return implode(PHP_EOL, $contents); |
| 170 | + } |
| 171 | +} |
0 commit comments