blob: dc56d652457b510add6dac0d5448babd81615db9 [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 /**
adminab4f61b2006-09-25 22:12:32 +000090 * Optimize Table
91 *
92 * @access public
93 * @param string the table name
94 * @return bool
95 */
96 function optimize_table($table_name)
97 {
98 $sql = $this->_optimize_table($table_name);
99
100 if (is_bool($sql))
101 {
102 return $sql;
103 }
104
105 $query = $this->db->query($sql);
106 return current($query->result_array());
107 }
108
109 // --------------------------------------------------------------------
110
111 /**
admin31075cf2006-09-26 18:50:02 +0000112 * Optimize Database
113 *
114 * @access public
admine5bb9362006-09-27 00:31:22 +0000115 * @return array
admin31075cf2006-09-26 18:50:02 +0000116 */
117 function optimize_database()
118 {
119 $result = array();
120 foreach ($this->list_tables() as $table_name)
121 {
122 $sql = $this->_optimize_table($table_name);
123
124 if (is_bool($sql))
125 {
126 return $sql;
127 }
128
129 $query = $this->db->query($sql);
admine5bb9362006-09-27 00:31:22 +0000130
131 // Build the result array...
admin31075cf2006-09-26 18:50:02 +0000132 $res = current($query->result_array());
133 $key = str_replace($this->db->database.'.', '', current($res));
134 $keys = array_keys($res);
135 unset($res[$keys[0]]);
136
137 $result[$key] = $res;
138 }
139
140 return $result;
141 }
142
143 // --------------------------------------------------------------------
144
145 /**
adminab4f61b2006-09-25 22:12:32 +0000146 * Optimize Table
147 *
148 * @access public
149 * @param string the table name
150 * @return bool
151 */
152
153 function repair_table($table_name)
154 {
155 $sql = $this->_repair_table($table_name);
156
157 if (is_bool($sql))
158 {
159 return $sql;
160 }
161
162 $query = $this->db->query($sql);
163 return current($query->result_array());
164 }
admin83b05a82006-09-25 21:06:46 +0000165
166 // --------------------------------------------------------------------
167
168 /**
169 * Drop Table
170 *
171 * @access public
172 * @param string the table name
173 * @return bool
174 */
adminab4f61b2006-09-25 22:12:32 +0000175 function drop_table($table_name)
admin83b05a82006-09-25 21:06:46 +0000176 {
adminab4f61b2006-09-25 22:12:32 +0000177 $sql = $this->_drop_table($table_name);
admin83b05a82006-09-25 21:06:46 +0000178
179 if (is_bool($sql))
180 {
181 return $sql;
182 }
183
184 return $this->db->query($sql);
185 }
186
admin3ed8c512006-09-29 23:26:28 +0000187 // --------------------------------------------------------------------
admin83b05a82006-09-25 21:06:46 +0000188
admin3ed8c512006-09-29 23:26:28 +0000189 /**
190 * Generate CVS from a query result object
191 *
192 * @access public
193 * @param object The query result object
194 * @param string The delimiter - tab by default
195 * @param string The newline character - \n by default
196 * @return string
197 */
198 function cvs_from_result($query, $delim = "\t", $newline = "\n")
199 {
200 if ( ! is_object($query) OR ! method_exists($query, 'field_names'))
201 {
202 show_error('You must submit a valid result object');
203 }
204
205 $out = '';
206
207 // First generate the headings from the table column names
208 foreach ($query->field_names() as $name)
209 {
210 $out .= $name.$delim;
211 }
212
213 $out = rtrim($out);
214 $out .= $newline;
215
216 // Next blast through the result array and build out the rows
217 foreach ($query->result_array() as $row)
218 {
219 foreach ($row as $item)
220 {
221 $out .= $item.$delim;
222 }
223 $out = rtrim($out);
224 $out .= $newline;
225 }
226
227 return $out;
228 }
229
230 // --------------------------------------------------------------------
231
232 /**
233 * Generate XML data from a query result object
234 *
235 * @access public
236 * @param object The query result object
237 * @param array Any preferences
238 * @return string
239 */
240 function xml_from_result($query, $params = array())
241 {
242 if ( ! is_object($query) OR ! method_exists($query, 'field_names'))
243 {
244 show_error('You must submit a valid result object');
245 }
246
247 // Set our default values
248 foreach (array('root' => 'root', 'element' => 'element', 'newline' => "\n", 'tab' => "\t") as $key => $val)
249 {
250 if ( ! isset($params[$key]))
251 {
252 $params[$key] = $val;
253 }
254 }
255
256 // Create variables for convenience
257 extract($params);
258
259 // Load the xml helper
260 $obj =& get_instance();
261 $obj->load->helper('xml');
262
263 // Generate the result
264 $xml = "<{$root}/>".$newline;
265 foreach ($query->result_array() as $row)
266 {
267 $xml .= $tab."<{$element}/>".$newline;
268
269 foreach ($row as $key => $val)
270 {
271 $xml .= $tab.$tab."<{$key}>".xml_convert($val)."</{$key}>".$newline;
272 }
273 $xml .= $tab."</{$element}>".$newline;
274 }
275 $xml .= "</$root>".$newline;
276
277 return $xml;
278 }
279
280 // --------------------------------------------------------------------
281
282 /**
283 * Database Backup
284 *
285 * @access public
286 * @return void
287 */
admin3dd978f2006-09-30 19:24:45 +0000288 function backup($params = array())
admin3ed8c512006-09-29 23:26:28 +0000289 {
admin3dd978f2006-09-30 19:24:45 +0000290 // If the parameters have not been submitted as an
291 // array then we know that it is simply the table
292 // name, which is a valid short cut.
293 if (is_string($params))
294 {
295 $params = array('tables' => $params);
296 }
297
298 // ------------------------------------------------------
299
300 // Set up our default preferences
301 $prefs = array(
302 'tables' => array(),
303 'ignore' => array(),
304 'format' => 'gzip', // gzip, zip, txt
305 'action' => 'download', // download, archive, echo, return
306 'filename' => '',
307 'filepath' => '',
308 'add_drop' => TRUE,
309 'add_insert' => TRUE,
310 'newline' => "\n"
311 );
312
313 // Did the user submit any preferences? If so set them....
314 if (count($params) > 0)
315 {
316 foreach ($prefs as $key => $val)
317 {
318 if (isset($params[$key]))
319 {
320 $prefs[$key] = $params[$key];
321 }
322 }
323 }
324
325 // ------------------------------------------------------
326
327 // Are we backing up a complete database or individual tables?
328 // If no table names were submitted we'll fetch the entire table list
329 if (count($prefs['tables']) == 0)
330 {
331 $prefs['tables'] = $this->list_tables();
332 }
333
334 // ------------------------------------------------------
335
336 // Validate the format
337 if ( ! in_array($prefs['format'], array('gzip', 'zip', 'txt'), TRUE))
338 {
339 $prefs['format'] = 'txt';
340 }
341
342 // ------------------------------------------------------
343
344 // Is the encoder supported? If not, we'll either issue an
345 // error or use plain text depending on the debug settings
346 if (($prefs['format'] == 'gzip' AND ! @function_exists('gzencode'))
347 OR ($prefs['format'] == 'zip' AND ! @function_exists('gzcompress')))
348 {
349 if ($this->db->db_debug)
350 {
351 return $this->db->display_error('db_unsuported_compression');
352 }
353
354 $prefs['format'] = 'txt';
355 }
356
357 // ------------------------------------------------------
358
359 // Set the filename if not provided
360 if ($prefs['filename'] == '')
361 {
362 $prefs['filename'] = (count($prefs['tables']) == 1) ? $prefs['tables'] : $this->db->database;
363 $prefs['filename'] .= '_'.date('Y-m-d_H-i', time());
364 }
365
366 // ------------------------------------------------------
367
368 // If we are archiving the export, does this filepath exist
369 // and resolve to a writable directory
370 if ($prefs['action'] == 'archive')
371 {
372 if ($prefs['filepath'] == '' OR ! is_writable($prefs['filepath']))
373 {
374 if ($this->db->db_debug)
375 {
376 return $this->db->display_error('db_filepath_error');
377 }
378
379 $prefs['action'] = 'download';
380 }
381 }
382
383 // ------------------------------------------------------
384
385 // Are we returning the backup data? If so, we're done...
386 if ($prefs['action'] == 'return')
387 {
388 return $this->_backup($prefs);
389 }
390
391 // ------------------------------------------------------
392
393 // Are we echoing the backup? If so, format the data and spit it at the screen...
394 if ($prefs['action'] == 'echo')
395 {
396 echo '<pre>';
397 echo htmlspecialchars($this->_backup($prefs));
398 echo '</pre>';
399
400 return TRUE;
401 }
402
403 // ------------------------------------------------------
404
405 // Are we archiving the data to the server?
406 if ($prefs['action'] == 'archive')
407 {
408 // Make sure the filepath has a trailing slash
409 if (ereg("/$", $prefs['filepath']) === FALSE)
410 {
411 $prefs['filepath'] .= '/';
412 }
413
414 // Assemble the path and tack on the file extension
415 $ext = array('gzip' => 'gz', 'zip' => 'zip', 'txt' => 'sql');
416 $path = $prefs['filepath'].$prefs['filename'].$ext[$prefs['format']];
417
418 // Load the file helper
419 $obj =& get_instance();
420 $obj->load->helper('file');
421
422 // Write the file based on type
423 switch ($prefs['format'])
424 {
425 case 'gzip' :
426 write_file($path, gzencode($this->_backup($prefs)));
427 return TRUE;
428 break;
429 case 'txt' :
430 write_file($path, $this->_backup($prefs));
431 return TRUE;
432 break;
433 default :
434 require BASEPATH.'libraries/Zip.php';
435 $zip = new Zip;
436 $zip->add_file($this->_backup($prefs), $prefs['filename'].'.sql');
437 write_file($path, $zip->output_zipfile());
438 return TRUE;
439 break;
440 }
441
442 }
443
444 // ------------------------------------------------------
445
446 // Set the mime type used in the server header
447 switch ($prefs['format'])
448 {
449 case 'zip' : $mime = 'application/x-zip';
450 break;
451 case 'gzip' : $mime = 'application/x-gzip';
452 break;
453 default :
454 if (strstr($_SERVER['HTTP_USER_AGENT'], "MSIE") || strstr($_SERVER['HTTP_USER_AGENT'], "OPERA"))
455 {
456 $mime = 'application/octetstream';
457 }
458 else
459 {
460 $mime = 'application/octet-stream';
461 }
462 break;
463 }
464
465 // Grab the super object
466 $obj =& get_instance();
467
468 // Remap the file extensions
469 $ext = array('gzip' => 'gz', 'zip' => 'zip', 'txt' => 'sql');
470
471 // Send headers
472 if (strstr($_SERVER['HTTP_USER_AGENT'], "MSIE"))
473 {
474 $obj->output->set_header('Content-Type: '.$mime);
475 $obj->output->set_header('Content-Disposition: inline; filename="'.$prefs['filename'].'.'.$ext[$prefs['format']].'"');
476 $obj->output->set_header('Expires: 0');
477 $obj->output->set_header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
478 $obj->output->set_header('Pragma: public');
479 }
480 else
481 {
482 $obj->output->set_header('Content-Type: '.$mime);
483 $obj->output->set_header('Content-Disposition: attachment; filename="'.$prefs['filename'].'.'.$ext[$prefs['format']].'"');
484 $obj->output->set_header('Expires: 0');
485 $obj->output->set_header('Pragma: no-cache');
486 }
487
488
489 // Write the file based on type
490 switch ($prefs['format'])
491 {
492 case 'gzip' : $obj->output->set_output(gzencode($this->_backup($prefs)));
493 break;
494 case 'txt' : $obj->output->set_output($this->_backup($prefs));
495 break;
496 default :
497 require BASEPATH.'libraries/Zip.php';
498
499 $zip = new Zip;
500 $zip->add_file($this->_backup($prefs), $prefs['filename'].'.sql');
501 $obj->output->set_output($zip->output_zipfile());
502 break;
503 }
504
505 return TRUE;
admin3ed8c512006-09-29 23:26:28 +0000506 }
admin7b613c72006-09-24 18:05:17 +0000507
508
admin3dd978f2006-09-30 19:24:45 +0000509
510
511
512
admin7b613c72006-09-24 18:05:17 +0000513}
514
515?>