blob: e568bce02a065fcc342223cc3ec9cebdbfacaf99 [file] [log] [blame]
admin7b613c72006-09-24 18:05:17 +00001<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
2/**
3 * Code Igniter
4 *
5 * An open source application development framework for PHP 4.3.2 or newer
6 *
7 * @package CodeIgniter
8 * @author Rick Ellis
9 * @copyright Copyright (c) 2006, pMachine, Inc.
10 * @license http://www.codeignitor.com/user_guide/license.html
11 * @link http://www.codeigniter.com
12 * @since Version 1.0
13 * @filesource
14 */
admine79dc712006-09-26 03:52:45 +000015
admin7b613c72006-09-24 18:05:17 +000016// ------------------------------------------------------------------------
17
18/**
19 * Database Utility Class
20 *
21 * @category Database
22 * @author Rick Ellis
23 * @link http://www.codeigniter.com/user_guide/database/
24 */
25class CI_DB_utility {
26
admina5e812c2006-09-25 02:17:30 +000027 var $db;
admin3ed8c512006-09-29 23:26:28 +000028 var $cache = array();
admin7b613c72006-09-24 18:05:17 +000029
admin41a16852006-09-26 18:17:19 +000030 /**
31 * Constructor
32 *
33 * Grabs the CI super object instance so we can access it.
34 *
35 */
admina5e812c2006-09-25 02:17:30 +000036 function CI_DB_utility()
37 {
38 // Assign the main database object to $this->db
39 $obj =& get_instance();
40 $this->db =& $obj->db;
admin910d8622006-09-26 02:09:05 +000041
42 log_message('debug', "Database Utility Class Initialized");
admina5e812c2006-09-25 02:17:30 +000043 }
44
admin7b613c72006-09-24 18:05:17 +000045 // --------------------------------------------------------------------
46
47 /**
admin6cec6a52006-09-25 06:56:49 +000048 * Create database
49 *
50 * @access public
51 * @param string the database name
52 * @return bool
53 */
adminab4f61b2006-09-25 22:12:32 +000054 function create_database($db_name)
admin6cec6a52006-09-25 06:56:49 +000055 {
adminab4f61b2006-09-25 22:12:32 +000056 $sql = $this->_create_database($db_name);
admin6cec6a52006-09-25 06:56:49 +000057
58 if (is_bool($sql))
59 {
60 return $sql;
61 }
62
63 return $this->db->query($sql);
64 }
65
66 // --------------------------------------------------------------------
67
admin83b05a82006-09-25 21:06:46 +000068 /**
69 * Drop database
70 *
71 * @access public
72 * @param string the database name
73 * @return bool
74 */
adminab4f61b2006-09-25 22:12:32 +000075 function drop_database($db_name)
adminbb1d4392006-09-24 20:14:38 +000076 {
adminab4f61b2006-09-25 22:12:32 +000077 $sql = $this->_drop_database($db_name);
admin83b05a82006-09-25 21:06:46 +000078
79 if (is_bool($sql))
80 {
81 return $sql;
82 }
83
84 return $this->db->query($sql);
adminbb1d4392006-09-24 20:14:38 +000085 }
admin83b05a82006-09-25 21:06:46 +000086
87 // --------------------------------------------------------------------
88
89 /**
adminb2a9cec2006-10-01 03:38:04 +000090 * List databases
91 *
92 * @access public
93 * @return bool
94 */
95 function list_databases()
96 {
97 // Is there a cached result?
98 if (isset($this->cache['db_names']))
99 {
100 return $this->cache['db_names'];
101 }
102
103 $query = $this->db->query($this->_list_database());
104 $dbs = array();
105 if ($query->num_rows() > 0)
106 {
107 foreach ($query->result_array() as $row)
108 {
109 $dbs[] = current($row);
110 }
111 }
112
113 return $this->cache['db_names'] =& $dbs;
114 }
115
116 // --------------------------------------------------------------------
117
118 /**
adminab4f61b2006-09-25 22:12:32 +0000119 * Optimize Table
120 *
121 * @access public
122 * @param string the table name
123 * @return bool
124 */
125 function optimize_table($table_name)
126 {
127 $sql = $this->_optimize_table($table_name);
128
129 if (is_bool($sql))
130 {
131 return $sql;
132 }
133
134 $query = $this->db->query($sql);
135 return current($query->result_array());
136 }
137
138 // --------------------------------------------------------------------
139
140 /**
admin31075cf2006-09-26 18:50:02 +0000141 * Optimize Database
142 *
143 * @access public
admine5bb9362006-09-27 00:31:22 +0000144 * @return array
admin31075cf2006-09-26 18:50:02 +0000145 */
146 function optimize_database()
147 {
148 $result = array();
149 foreach ($this->list_tables() as $table_name)
150 {
151 $sql = $this->_optimize_table($table_name);
152
153 if (is_bool($sql))
154 {
155 return $sql;
156 }
157
158 $query = $this->db->query($sql);
admine5bb9362006-09-27 00:31:22 +0000159
160 // Build the result array...
admin31075cf2006-09-26 18:50:02 +0000161 $res = current($query->result_array());
162 $key = str_replace($this->db->database.'.', '', current($res));
163 $keys = array_keys($res);
164 unset($res[$keys[0]]);
165
166 $result[$key] = $res;
167 }
168
169 return $result;
170 }
171
172 // --------------------------------------------------------------------
173
174 /**
adminab4f61b2006-09-25 22:12:32 +0000175 * Optimize Table
176 *
177 * @access public
178 * @param string the table name
179 * @return bool
180 */
181
182 function repair_table($table_name)
183 {
184 $sql = $this->_repair_table($table_name);
185
186 if (is_bool($sql))
187 {
188 return $sql;
189 }
190
191 $query = $this->db->query($sql);
192 return current($query->result_array());
193 }
admin83b05a82006-09-25 21:06:46 +0000194
195 // --------------------------------------------------------------------
196
197 /**
198 * Drop Table
199 *
200 * @access public
201 * @param string the table name
202 * @return bool
203 */
adminab4f61b2006-09-25 22:12:32 +0000204 function drop_table($table_name)
admin83b05a82006-09-25 21:06:46 +0000205 {
adminab4f61b2006-09-25 22:12:32 +0000206 $sql = $this->_drop_table($table_name);
admin83b05a82006-09-25 21:06:46 +0000207
208 if (is_bool($sql))
209 {
210 return $sql;
211 }
212
213 return $this->db->query($sql);
214 }
215
admin3ed8c512006-09-29 23:26:28 +0000216 // --------------------------------------------------------------------
admin83b05a82006-09-25 21:06:46 +0000217
admin3ed8c512006-09-29 23:26:28 +0000218 /**
219 * Generate CVS from a query result object
220 *
221 * @access public
222 * @param object The query result object
223 * @param string The delimiter - tab by default
224 * @param string The newline character - \n by default
225 * @return string
226 */
227 function cvs_from_result($query, $delim = "\t", $newline = "\n")
228 {
229 if ( ! is_object($query) OR ! method_exists($query, 'field_names'))
230 {
231 show_error('You must submit a valid result object');
232 }
233
234 $out = '';
235
236 // First generate the headings from the table column names
237 foreach ($query->field_names() as $name)
238 {
239 $out .= $name.$delim;
240 }
241
242 $out = rtrim($out);
243 $out .= $newline;
244
245 // Next blast through the result array and build out the rows
246 foreach ($query->result_array() as $row)
247 {
248 foreach ($row as $item)
249 {
250 $out .= $item.$delim;
251 }
252 $out = rtrim($out);
253 $out .= $newline;
254 }
255
256 return $out;
257 }
258
259 // --------------------------------------------------------------------
260
261 /**
262 * Generate XML data from a query result object
263 *
264 * @access public
265 * @param object The query result object
266 * @param array Any preferences
267 * @return string
268 */
269 function xml_from_result($query, $params = array())
270 {
271 if ( ! is_object($query) OR ! method_exists($query, 'field_names'))
272 {
273 show_error('You must submit a valid result object');
274 }
275
276 // Set our default values
277 foreach (array('root' => 'root', 'element' => 'element', 'newline' => "\n", 'tab' => "\t") as $key => $val)
278 {
279 if ( ! isset($params[$key]))
280 {
281 $params[$key] = $val;
282 }
283 }
284
285 // Create variables for convenience
286 extract($params);
287
288 // Load the xml helper
289 $obj =& get_instance();
290 $obj->load->helper('xml');
291
292 // Generate the result
293 $xml = "<{$root}/>".$newline;
294 foreach ($query->result_array() as $row)
295 {
296 $xml .= $tab."<{$element}/>".$newline;
297
298 foreach ($row as $key => $val)
299 {
300 $xml .= $tab.$tab."<{$key}>".xml_convert($val)."</{$key}>".$newline;
301 }
302 $xml .= $tab."</{$element}>".$newline;
303 }
304 $xml .= "</$root>".$newline;
305
306 return $xml;
307 }
308
309 // --------------------------------------------------------------------
310
311 /**
312 * Database Backup
313 *
314 * @access public
315 * @return void
316 */
admin3dd978f2006-09-30 19:24:45 +0000317 function backup($params = array())
admin3ed8c512006-09-29 23:26:28 +0000318 {
admin3dd978f2006-09-30 19:24:45 +0000319 // If the parameters have not been submitted as an
320 // array then we know that it is simply the table
321 // name, which is a valid short cut.
322 if (is_string($params))
323 {
324 $params = array('tables' => $params);
325 }
326
327 // ------------------------------------------------------
328
329 // Set up our default preferences
330 $prefs = array(
331 'tables' => array(),
332 'ignore' => array(),
333 'format' => 'gzip', // gzip, zip, txt
334 'action' => 'download', // download, archive, echo, return
335 'filename' => '',
336 'filepath' => '',
337 'add_drop' => TRUE,
338 'add_insert' => TRUE,
339 'newline' => "\n"
340 );
341
342 // Did the user submit any preferences? If so set them....
343 if (count($params) > 0)
344 {
345 foreach ($prefs as $key => $val)
346 {
347 if (isset($params[$key]))
348 {
349 $prefs[$key] = $params[$key];
350 }
351 }
352 }
353
354 // ------------------------------------------------------
355
356 // Are we backing up a complete database or individual tables?
357 // If no table names were submitted we'll fetch the entire table list
358 if (count($prefs['tables']) == 0)
359 {
360 $prefs['tables'] = $this->list_tables();
361 }
362
363 // ------------------------------------------------------
364
365 // Validate the format
366 if ( ! in_array($prefs['format'], array('gzip', 'zip', 'txt'), TRUE))
367 {
368 $prefs['format'] = 'txt';
369 }
370
371 // ------------------------------------------------------
372
373 // Is the encoder supported? If not, we'll either issue an
374 // error or use plain text depending on the debug settings
375 if (($prefs['format'] == 'gzip' AND ! @function_exists('gzencode'))
376 OR ($prefs['format'] == 'zip' AND ! @function_exists('gzcompress')))
377 {
378 if ($this->db->db_debug)
379 {
380 return $this->db->display_error('db_unsuported_compression');
381 }
382
383 $prefs['format'] = 'txt';
384 }
385
386 // ------------------------------------------------------
387
388 // Set the filename if not provided
389 if ($prefs['filename'] == '')
390 {
391 $prefs['filename'] = (count($prefs['tables']) == 1) ? $prefs['tables'] : $this->db->database;
392 $prefs['filename'] .= '_'.date('Y-m-d_H-i', time());
393 }
394
395 // ------------------------------------------------------
396
397 // If we are archiving the export, does this filepath exist
398 // and resolve to a writable directory
399 if ($prefs['action'] == 'archive')
400 {
401 if ($prefs['filepath'] == '' OR ! is_writable($prefs['filepath']))
402 {
403 if ($this->db->db_debug)
404 {
405 return $this->db->display_error('db_filepath_error');
406 }
407
408 $prefs['action'] = 'download';
409 }
410 }
411
412 // ------------------------------------------------------
413
414 // Are we returning the backup data? If so, we're done...
415 if ($prefs['action'] == 'return')
416 {
417 return $this->_backup($prefs);
418 }
419
420 // ------------------------------------------------------
421
422 // Are we echoing the backup? If so, format the data and spit it at the screen...
423 if ($prefs['action'] == 'echo')
424 {
425 echo '<pre>';
426 echo htmlspecialchars($this->_backup($prefs));
427 echo '</pre>';
428
429 return TRUE;
430 }
431
432 // ------------------------------------------------------
433
434 // Are we archiving the data to the server?
435 if ($prefs['action'] == 'archive')
436 {
437 // Make sure the filepath has a trailing slash
438 if (ereg("/$", $prefs['filepath']) === FALSE)
439 {
440 $prefs['filepath'] .= '/';
441 }
442
443 // Assemble the path and tack on the file extension
444 $ext = array('gzip' => 'gz', 'zip' => 'zip', 'txt' => 'sql');
445 $path = $prefs['filepath'].$prefs['filename'].$ext[$prefs['format']];
446
447 // Load the file helper
448 $obj =& get_instance();
449 $obj->load->helper('file');
450
451 // Write the file based on type
452 switch ($prefs['format'])
453 {
454 case 'gzip' :
455 write_file($path, gzencode($this->_backup($prefs)));
456 return TRUE;
457 break;
458 case 'txt' :
459 write_file($path, $this->_backup($prefs));
460 return TRUE;
461 break;
462 default :
463 require BASEPATH.'libraries/Zip.php';
464 $zip = new Zip;
465 $zip->add_file($this->_backup($prefs), $prefs['filename'].'.sql');
466 write_file($path, $zip->output_zipfile());
467 return TRUE;
468 break;
469 }
470
471 }
472
473 // ------------------------------------------------------
474
475 // Set the mime type used in the server header
476 switch ($prefs['format'])
477 {
478 case 'zip' : $mime = 'application/x-zip';
479 break;
480 case 'gzip' : $mime = 'application/x-gzip';
481 break;
482 default :
483 if (strstr($_SERVER['HTTP_USER_AGENT'], "MSIE") || strstr($_SERVER['HTTP_USER_AGENT'], "OPERA"))
484 {
485 $mime = 'application/octetstream';
486 }
487 else
488 {
489 $mime = 'application/octet-stream';
490 }
491 break;
492 }
493
494 // Grab the super object
495 $obj =& get_instance();
496
497 // Remap the file extensions
498 $ext = array('gzip' => 'gz', 'zip' => 'zip', 'txt' => 'sql');
499
500 // Send headers
501 if (strstr($_SERVER['HTTP_USER_AGENT'], "MSIE"))
502 {
503 $obj->output->set_header('Content-Type: '.$mime);
504 $obj->output->set_header('Content-Disposition: inline; filename="'.$prefs['filename'].'.'.$ext[$prefs['format']].'"');
505 $obj->output->set_header('Expires: 0');
506 $obj->output->set_header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
507 $obj->output->set_header('Pragma: public');
508 }
509 else
510 {
511 $obj->output->set_header('Content-Type: '.$mime);
512 $obj->output->set_header('Content-Disposition: attachment; filename="'.$prefs['filename'].'.'.$ext[$prefs['format']].'"');
513 $obj->output->set_header('Expires: 0');
514 $obj->output->set_header('Pragma: no-cache');
515 }
516
517
518 // Write the file based on type
519 switch ($prefs['format'])
520 {
521 case 'gzip' : $obj->output->set_output(gzencode($this->_backup($prefs)));
522 break;
523 case 'txt' : $obj->output->set_output($this->_backup($prefs));
524 break;
525 default :
526 require BASEPATH.'libraries/Zip.php';
527
528 $zip = new Zip;
529 $zip->add_file($this->_backup($prefs), $prefs['filename'].'.sql');
530 $obj->output->set_output($zip->output_zipfile());
531 break;
532 }
533
534 return TRUE;
admin3ed8c512006-09-29 23:26:28 +0000535 }
admin7b613c72006-09-24 18:05:17 +0000536
537
admin3dd978f2006-09-30 19:24:45 +0000538
539
540
541
admin7b613c72006-09-24 18:05:17 +0000542}
543
544?>