1: <?php
2:
3: App::uses('Shell', 'Console');
4: App::uses('ConnectionManager', 'Model');
5: App::uses('DatasourceDumperManager', 'Datasources.Lib');
6:
7: 8: 9: 10: 11: 12:
13: class DumperShell extends Shell {
14:
15: 16: 17: 18:
19: private $connection;
20:
21: 22: 23: 24:
25: private $dumpName;
26:
27: 28: 29: 30:
31: private $dumpPath;
32:
33: 34: 35: 36:
37: private $dumper;
38:
39: 40: 41: 42:
43: private $clear;
44:
45: 46: 47: 48: 49:
50: public function getOptionParser() {
51: $parser = parent::getOptionParser();
52: $parser->description('Database utilities.');
53: $parser->addOptions(
54: array(
55: 'connection' => array(
56: 'short' => 'c',
57: 'default' => 'default',
58: 'choices' => $this->_optionParserConnectionArgumentChoices(),
59: 'help' => __d('datasources','Set db config <config>. Uses \'default\' if none is specified.')
60: ),
61: 'path' => array(
62: 'default' => false,
63: 'help' => __d('datasources','Alternative path to dump')
64: ),
65: 'clear' => array(
66: 'default' => false,
67: 'boolean' => true,
68: 'help' => __d('datasources','Clear database objects before load')
69: )
70: )
71: );
72: $parser->addSubcommands(array(
73: 'load' => array(
74: 'help' => __d('datasources','Load a database dump')
75: ),
76: 'show' => array(
77: 'help' => __d('datasources','List all database dumps')
78: ),
79: 'dump' => array(
80: 'help' => __d('datasources','Dump database')
81: ),
82: 'remove' => array(
83: 'help' => __d('datasources','Delete a dump')
84: ),
85: 'clear' => array(
86: 'help' => __d('datasources','Clear database')
87: )
88: ));
89:
90: return $parser;
91: }
92:
93: private function _optionParserConnectionArgumentChoices() {
94: return array_keys(ConnectionManager::enumConnectionObjects());
95: }
96:
97: public function main() {
98: $this->out($this->getOptionParser()->help());
99: }
100:
101: public function clear() {
102: $this->_parseArgs();
103:
104: $dumper = $this->_getDumper($this->connection);
105: $dumper->clear(ConnectionManager::getDataSource($this->connection));
106: }
107:
108: public function dump() {
109: $this->_parseArgs();
110:
111: $this->out("Connection: {$this->connection}");
112:
113: $dumper = $this->_getDumper($this->connection);
114: $dumpPath = $this->_newDumpPath();
115:
116: $dumper->dump(
117: ConnectionManager::getDataSource($this->connection)
118: , $dumpPath
119: );
120:
121: $this->out("Dump created: \"{$dumpPath}\"");
122: }
123:
124: public function load() {
125: $this->_parseArgs();
126: $this->_outArguments();
127:
128: if ($this->dumpPath) {
129: if (file_exists($this->dumpPath)) {
130: $dataSource = ConnectionManager::getDataSource($this->connection);
131: if ($this->clear) {
132: $this->dumper->clear($dataSource);
133: }
134:
135: $this->dumper->load(
136: $dataSource
137: , $this->dumpPath
138: );
139: $this->out("Dump loaded: \"{$this->dumpPath}\"");
140: } else {
141: $this->out("Dump not found: \"{$this->dumpPath}\"");
142: }
143: } else {
144: $this->out("No dump name informed");
145: }
146: }
147:
148: public function remove() {
149: $this->_parseArgs();
150:
151: if ($this->dumpName) {
152: if (($dump = $this->_findDump())) {
153: unlink($dump['path']);
154: $this->out("\"{$dump['path']}\" was deleted.");
155: } else {
156: $this->out("Dump not found with name \"{$this->dumpName}\"");
157: }
158: } else {
159: $this->out("No dump name informed");
160: }
161: }
162:
163: private function _outArguments() {
164: $this->out('Connection: ' . $this->connection);
165: $this->out('Dump path: ' . $this->dumpPath);
166: $this->out('Dump name: ' . $this->dumpName);
167: $this->out('Clear: ' . ($this->clear ? 'yes' : 'no'));
168: }
169:
170: private function _newDumpPath() {
171: $ds = ConnectionManager::getDataSource($this->connection);
172: return $this->_getDumpsDirectory() . DS . $this->connection .
173: '_' .
174: date('Y-m-d_H-i-s') .
175: '_' .
176: str_replace('/', '-', $ds->config['datasource']);
177: }
178:
179: private function _parseArgs() {
180: $this->connection = $this->params['connection'];
181:
182: if ($this->params['path'] !== false) {
183: $this->dumpPath = $this->params['path'];
184: $this->dumpName = basename($this->dumpPath);
185: } else if (!empty($this->args[0])) {
186: $this->dumpName = $this->args[0];
187: $this->dumpPath = $this->_getDumpsDirectory() . DS . $this->dumpName;
188: } else {
189: $this->dumpName = '';
190: $this->dumpPath = '';
191: }
192:
193: $this->dumper = $this->_getDumper($this->connection);
194: $this->clear = $this->params['clear'];
195: }
196:
197: public function show() {
198: $this->out("Dumps directory: \"{$this->_getDumpsDirectory()}\"");
199: $this->hr();
200:
201: $total = 0;
202: foreach ($this->_listDumps() as $dump) {
203: $this->out("{$dump['name']}: {$dump['connection']}|{$dump['date']}|{$dump['datasource']}");
204: $total++;
205: }
206:
207: $this->hr();
208: $this->out("Total: $total");
209: }
210:
211: private function _getDumper($connection) {
212: return DatasourceDumperManager::getDumper(ConnectionManager::getDataSource($connection));
213: }
214:
215: private function _getDumpsDirectory() {
216: $dir = TMP . DS . 'datasource-dump';
217:
218: if (file_exists($dir)) {
219: if (is_dir($dir)) {
220: return $dir;
221: } else {
222: throw new Exception("Directory \"$dir\" exists, but is not a directory");
223: }
224: } else if (mkdir($dir)) {
225: return $dir;
226: } else {
227: throw new Exception("Was not possible to create directory \"$dir\"");
228: }
229: }
230:
231: }