root/wp-dbmanager/trunk/wp-dbmanager.php

Revision 52841, 23.9 kB (checked in by GamerZ, 2 days ago)

Works For WordPress 2.6

Line 
1 <?php
2 /*
3 Plugin Name: WP-DBManager
4 Plugin URI: http://lesterchan.net/portfolio/programming/php/
5 Description: Manages your Wordpress database. Allows you to optimize database, repair database, backup database, restore database, delete backup database , drop/empty tables and run selected queries. Supports automatic scheduling of backing up and optimizing of database.
6 Version: 2.31
7 Author: Lester 'GaMerZ' Chan
8 Author URI: http://lesterchan.net
9 */
10
11
12 /* 
13     Copyright 2008  Lester Chan  (email : lesterchan@gmail.com)
14
15     This program is free software; you can redistribute it and/or modify
16     it under the terms of the GNU General Public License as published by
17     the Free Software Foundation; either version 2 of the License, or
18     (at your option) any later version.
19
20     This program is distributed in the hope that it will be useful,
21     but WITHOUT ANY WARRANTY; without even the implied warranty of
22     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23     GNU General Public License for more details.
24
25     You should have received a copy of the GNU General Public License
26     along with this program; if not, write to the Free Software
27     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28 */
29
30
31 ### Use WordPress 2.6 Constants
32 if (!defined('WP_CONTENT_DIR')) {
33     define( 'WP_CONTENT_DIR', ABSPATH.'wp-content');
34 }
35 if (!defined('WP_CONTENT_URL')) {
36     define('WP_CONTENT_URL', get_option('siteurl').'/wp-content');
37 }
38 if (!defined('WP_PLUGIN_DIR')) {
39     define('WP_PLUGIN_DIR', WP_CONTENT_DIR.'/plugins');
40 }
41 if (!defined('WP_PLUGIN_URL')) {
42     define('WP_PLUGIN_URL', WP_CONTENT_URL.'/plugins');
43 }
44
45
46 ### Create Text Domain For Translations
47 add_action('init', 'dbmanager_textdomain');
48 function dbmanager_textdomain() {
49     if (!function_exists('wp_print_styles')) {
50         load_plugin_textdomain('wp-dbmanager', 'wp-content/plugins/wp-dbmanager');
51     } else {
52         load_plugin_textdomain('wp-dbmanager', false, 'wp-dbmanager');
53     }
54 }
55
56
57 ### Function: Database Manager Menu
58 add_action('admin_menu', 'dbmanager_menu');
59 function dbmanager_menu() {
60     if (function_exists('add_menu_page')) {
61         add_menu_page(__('Database', 'wp-dbmanager'), __('Database', 'wp-dbmanager'), 'manage_database', 'wp-dbmanager/database-manager.php');
62     }
63     if (function_exists('add_submenu_page')) {
64         add_submenu_page('wp-dbmanager/database-manager.php', __('Backup DB', 'wp-dbmanager'), __('Backup DB', 'wp-dbmanager'), 'manage_database', 'wp-dbmanager/database-backup.php');
65         add_submenu_page('wp-dbmanager/database-manager.php', __('Manage Backup DB', 'wp-dbmanager'), __('Manage Backup DB', 'wp-dbmanager'), 'manage_database', 'wp-dbmanager/database-manage.php');
66         add_submenu_page('wp-dbmanager/database-manager.php', __('Optimize DB', 'wp-dbmanager'), __('Optimize DB', 'wp-dbmanager'), 'manage_database', 'wp-dbmanager/database-optimize.php');
67         add_submenu_page('wp-dbmanager/database-manager.php', __('Repair DB', 'wp-dbmanager'), __('Repair DB', 'wp-dbmanager'), 'manage_database', 'wp-dbmanager/database-repair.php');
68         add_submenu_page('wp-dbmanager/database-manager.php', __('Empty/Drop Tables', 'wp-dbmanager'), __('Empty/Drop Tables', 'wp-dbmanager'), 'manage_database', 'wp-dbmanager/database-empty.php');
69         add_submenu_page('wp-dbmanager/database-manager.php', __('Run SQL Query', 'wp-dbmanager'), __('Run SQL Query', 'wp-dbmanager'), 'manage_database', 'wp-dbmanager/database-run.php');
70         add_submenu_page('wp-dbmanager/database-manager.php'__('DB Options', 'wp-dbmanager'),  __('DB Options', 'wp-dbmanager'), 'manage_database', 'wp-dbmanager/wp-dbmanager.php', 'dbmanager_options');
71         add_submenu_page('wp-dbmanager/database-manager.php', __('Uninstall WP-DBManager', 'wp-dbmanager'), __('Uninstall WP-DBManager', 'wp-dbmanager'), 'manage_database', 'wp-dbmanager/database-uninstall.php');
72     }
73 }
74
75
76 ### Funcion: Database Manager Cron
77 add_filter('cron_schedules', 'cron_dbmanager_reccurences');
78 add_action('dbmanager_cron_backup', 'cron_dbmanager_backup');
79 add_action('dbmanager_cron_optimize', 'cron_dbmanager_optimize');
80 function cron_dbmanager_backup() {
81     global $wpdb;
82     $backup_options = get_option('dbmanager_options');
83     $backup_email = stripslashes($backup_options['backup_email']);
84     if(intval($backup_options['backup_period']) > 0) {
85         $current_date = mysql2date(sprintf(__('%s @ %s', 'wp-dbmanager'), get_option('date_format'), get_option('time_format')), gmdate('Y-m-d H:i:s', current_time('timestamp')));
86         $backup = array();
87         $backup['date'] = current_time('timestamp');
88         $backup['mysqldumppath'] = $backup_options['mysqldumppath'];
89         $backup['mysqlpath'] = $backup_options['mysqlpath'];
90         $backup['path'] = $backup_options['path'];
91         $backup['command'] = '';
92         if(intval($backup_options['backup_gzip']) == 1) {
93             $backup['filename'] = $backup['date'].'_-_'.DB_NAME.'.sql.gz';
94             $backup['filepath'] = $backup['path'].'/'.$backup['filename'];
95             $backup['command'] = $backup['mysqldumppath'].' --host="'.DB_HOST.'" --user="'.DB_USER.'" --password="'.DB_PASSWORD.'" --add-drop-table --skip-lock-tables '.DB_NAME.' | gzip > '.$backup['filepath'];
96         } else {
97             $backup['filename'] = $backup['date'].'_-_'.DB_NAME.'.sql';
98             $backup['filepath'] = $backup['path'].'/'.$backup['filename'];
99             $backup['command'] = $backup['mysqldumppath'].' --host="'.DB_HOST.'" --user="'.DB_USER.'" --password="'.DB_PASSWORD.'" --add-drop-table --skip-lock-tables '.DB_NAME.' > '.$backup['filepath'];
100         }       
101         execute_backup($backup['command']);
102         if(!empty($backup_email)) {
103                 // Get And Read The Database Backup File
104                 $file_path = $backup['filepath'];
105                 $file_size = format_size(filesize($file_path));
106                 $file_date = mysql2date(sprintf(__('%s @ %s', 'wp-dbmanager'), get_option('date_format'), get_option('time_format')), gmdate('Y-m-d H:i:s', substr($backup['filename'], 0, 10)));
107                 $file = fopen($file_path,'rb');
108                 $file_data = fread($file,filesize($file_path));
109                 fclose($file);
110                 $file_data = chunk_split(base64_encode($file_data));
111                 // Create Mail To, Mail Subject And Mail Header
112                 $mail_subject = sprintf(__('%s Database Backup File For %s', 'wp-dbmanager'), get_bloginfo('name'), $file_date);
113                 $mail_header = 'From: '.get_bloginfo('name').' Administrator <'.get_option('admin_email').'>';
114                 // MIME Boundary
115                 $random_time = md5(time());
116                 $mime_boundary = "==WP-DBManager- $random_time";
117                 // Create Mail Header And Mail Message
118                 $mail_header .= "\nMIME-Version: 1.0\n" .
119                                         "Content-Type: multipart/mixed;\n" .
120                                         " boundary=\"{$mime_boundary}\"";
121                 $mail_message = __('Website Name:', 'wp-dbmanager').' '.get_bloginfo('name')."\n".
122                                         __('Website URL:', 'wp-dbmanager').' '.get_bloginfo('siteurl')."\n".
123                                         __('Backup File Name:', 'wp-dbmanager').' '.$backup['filename']."\n".
124                                         __('Backup File Date:', 'wp-dbmanager').' '.$file_date."\n".
125                                         __('Backup File Size:', 'wp-dbmanager').' '.$file_size."\n\n".
126                                         __('With Regards,', 'wp-dbmanager')."\n".
127                                         get_bloginfo('name').' '. __('Administrator', 'wp-dbmanager')."\n".
128                                         get_bloginfo('siteurl');
129                 $mail_message = "This is a multi-part message in MIME format.\n\n" .
130                                         "--{$mime_boundary}\n" .
131                                         "Content-Type: text/plain; charset=\"utf-8\"\n" .
132                                         "Content-Transfer-Encoding: 7bit\n\n".$mail_message."\n\n";               
133                 $mail_message .= "--{$mime_boundary}\n" .
134                                         "Content-Type: application/octet-stream;\n" .
135                                         " name=\"{$backup['filename']}\"\n" .
136                                         "Content-Disposition: attachment;\n" .
137                                         " filename=\"{$backup['filename']}\"\n" .
138                                         "Content-Transfer-Encoding: base64\n\n" .
139                                         $file_data."\n\n--{$mime_boundary}--\n";
140             mail($backup_email, $mail_subject, $mail_message, $mail_header);
141         }
142     }
143     return;
144 }
145 function cron_dbmanager_optimize() {
146     global $wpdb;
147     $backup_options = get_option('dbmanager_options');
148     $optimize = intval($backup_options['optimize']);
149     $optimize_period = intval($backup_options['optimize_period']);
150     if($optimize_period > 0) {
151         $optimize_tables = array();
152         $tables = $wpdb->get_col("SHOW TABLES");
153             foreach($tables as $table_name) {
154                 $optimize_tables[] = '`'.$table_name.'`';
155         }
156         $wpdb->query('OPTIMIZE TABLE '.implode(',', $optimize_tables));
157     }
158     return;
159 }
160 function cron_dbmanager_reccurences() {
161     $backup_options = get_option('dbmanager_options');
162     $backup = intval($backup_options['backup'])*intval($backup_options['backup_period']);
163     $optimize = intval($backup_options['optimize'])*intval($backup_options['optimize_period']);
164     if($backup == 0) {
165         $backup = 31536000;
166     }
167     if($optimize == 0) {
168         $optimize = 31536000;
169     }
170     return array(
171         'dbmanager_backup' => array('interval' => $backup, 'display' => __('WP-DBManager Backup Schedule', 'wp-dbmanager')),
172         'dbmanager_optimize' => array('interval' => $optimize, 'display' => __('WP-DBManager Optimize Schedule', 'wp-dbmanager'))
173     );
174 }
175
176
177 ### Function: Auto Detect MYSQL and MYSQL Dump Paths
178 function detect_mysql() {
179     global $wpdb;
180     $paths = array('mysq' => '', 'mysqldump' => '');
181     if(substr(PHP_OS,0,3) == 'WIN') {
182         $mysql_install = $wpdb->get_row("SHOW VARIABLES LIKE 'basedir'");
183         if($mysql_install) {
184             $install_path = str_replace('\\', '/', $mysql_install->Value);
185             $paths['mysql'] = $install_path.'bin/mysql.exe';
186             $paths['mysqldump'] = $install_path.'bin/mysqldump.exe';
187         } else {
188             $paths['mysql'] = 'mysql.exe';
189             $paths['mysqldump'] = 'mysqldump.exe';
190         }
191     } else {
192         if(function_exists('exec')) {
193             $paths['mysql'] = @exec('which mysql');
194             $paths['mysqldump'] = @exec('which mysqldump');
195         } else {
196             $paths['mysql'] = 'mysql';
197             $paths['mysqldump'] = 'mysqldump';
198         }
199     }
200     return $paths;
201 }
202
203
204 ### Executes OS-Dependent mysqldump Command (By: Vlad Sharanhovich)
205 function execute_backup($command) {
206     $backup_options = get_option('dbmanager_options');
207     check_backup_files();
208     if(substr(PHP_OS, 0, 3) == 'WIN') {
209         $writable_dir = $backup_options['path'];
210         $tmpnam = $writable_dir.'/wp-dbmanager.bat';
211         $fp = fopen($tmpnam, 'w');
212         fwrite($fp, $command);
213         fclose($fp);
214         system($tmpnam.' > NUL', $error);
215         unlink($tmpnam);
216     } else {
217         passthru($command, $error);
218     }
219     return $error;
220 }
221
222
223 ### Function: Format Bytes Into KB/MB
224 if(!function_exists('format_size')) {
225     function format_size($rawSize) {
226         if($rawSize / 1073741824 > 1)
227             return round($rawSize/1048576, 1) . ' GiB';
228         else if ($rawSize / 1048576 > 1)
229             return round($rawSize/1048576, 1) . ' MiB';
230         else if ($rawSize / 1024 > 1)
231             return round($rawSize/1024, 1) . ' KiB';
232         else
233             return round($rawSize, 1) . ' bytes';
234     }
235 }
236
237
238 ### Function: Get File Extension
239 if(!function_exists('file_ext')) {
240     function file_ext($file_name) {
241         return substr(strrchr($file_name, '.'), 1);
242     }
243 }
244
245
246 ### Function: Check Folder Whether There Is Any File Inside
247 if(!function_exists('is_emtpy_folder')) {
248     function is_emtpy_folder($folder){
249        if(is_dir($folder) ){
250            $handle = opendir($folder);
251            while( (gettype( $name = readdir($handle)) != 'boolean')){
252                 if($name != '.htaccess') {
253                     $name_array[] = $name;
254                 }
255            }
256            foreach($name_array as $temp)
257                $folder_content .= $temp;
258
259            if($folder_content == '...')
260                return true;
261            else
262                return false;
263            closedir($handle);
264        }
265        else
266            return true;
267     }
268 }
269
270
271 ### Function: Make Sure Maximum Number Of Database Backup Files Does Not Exceed
272 function check_backup_files() {
273     $backup_options = get_option('dbmanager_options');
274     $database_files = array();
275     if(!is_emtpy_folder($backup_options['path'])) {
276         if ($handle = opendir($backup_options['path'])) {           
277             while (false !== ($file = readdir($handle))) {
278                 if ($file != '.' && $file != '..' && (file_ext($file) == 'sql' || file_ext($file) == 'gz')) {
279                     $database_files[] = $file;
280                 }
281             }
282             closedir($handle);
283             sort($database_files);
284         }
285     }
286     if(sizeof($database_files) >= $backup_options['max_backup']) {
287         @unlink($backup_options['path'].'/'.$database_files[0]);
288     }
289 }
290
291
292 ### Function: Database Manager Role
293 add_action('activate_wp-dbmanager/wp-dbmanager.php', 'dbmanager_init');
294 function dbmanager_init() {
295     global $wpdb;
296     $auto = detect_mysql();
297     // Add Options
298     $backup_options = array();
299     $backup_options['mysqldumppath'] = $auto['mysqldump'];
300     $backup_options['mysqlpath'] = $auto['mysql'];
301     $backup_options['path'] = str_replace('\\', '/', WP_CONTENT_DIR).'/backup-db';
302     $backup_options['max_backup'] = 10;
303     $backup_options['backup'] = 1;
304     $backup_options['backup_gzip'] = 0;
305     $backup_options['backup_period'] = 604800;
306     $backup_options['backup_email'] = get_option('admin_email');
307     $backup_options['optimize'] = 3;
308     $backup_options['optimize_period'] = 86400;
309     add_option('dbmanager_options', $backup_options, 'WP-DBManager Options');
310
311     // Create Backup Folder
312     if(!is_dir(WP_CONTENT_DIR.'/backup-db')) {
313         mkdir(WP_CONTENT_DIR.'/backup-db');
314     }
315
316     // Set 'manage_database' Capabilities To Administrator   
317     $role = get_role('administrator');
318     if(!$role->has_cap('manage_database')) {
319         $role->add_cap('manage_database');
320     }
321 }
322
323
324 ### Function: Download Database
325 add_action('init', 'download_database');
326 function download_database() {
327     if($_POST['do'] == 'Download' && !empty($_POST['database_file'])) {
328         if(strpos($_SERVER['HTTP_REFERER'], get_option('siteurl').'/wp-admin/admin.php?page=wp-dbmanager/database-manage.php') !== false) {
329             $backup_options = get_option('dbmanager_options');
330             $file_path = $backup_options['path'].'/'.$_POST['database_file'];
331             header("Pragma: public");
332             header("Expires: 0");
333             header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
334             header("Content-Type: application/force-download");
335             header("Content-Type: application/octet-stream");
336             header("Content-Type: application/download");
337             header("Content-Disposition: attachment; filename=".basename($file_path).";");
338             header("Content-Transfer-Encoding: binary");
339             header("Content-Length: ".filesize($file_path));
340             @readfile($file_path);
341         }
342         exit();
343     }
344 }
345
346
347 ### Function: Database Options
348 function dbmanager_options() {
349     global $wpdb;
350     $text = '';
351     $backup_options = array();
352     $backup_options = get_option('dbmanager_options');
353     if($_POST['Submit']) {
354         $backup_options['mysqldumppath'] = trim($_POST['db_mysqldumppath']);
355         $backup_options['mysqlpath'] = trim($_POST['db_mysqlpath']);
356         $backup_options['path'] = trim($_POST['db_path']);
357         $backup_options['max_backup'] = intval($_POST['db_max_backup']);
358         $backup_options['backup'] = intval($_POST['db_backup']);
359         $backup_options['backup_gzip'] = intval($_POST['db_backup_gzip']);
360         $backup_options['backup_period'] = intval($_POST['db_backup_period']);
361         $backup_options['backup_email'] = trim(addslashes($_POST['db_backup_email']));
362         $backup_options['optimize'] = intval($_POST['db_optimize']);
363         $backup_options['optimize_period'] = intval($_POST['db_optimize_period']);
364         $update_db_options = update_option('dbmanager_options', $backup_options);
365         if($update_db_options) {
366             $text = '<font color="green">'.__('Database Options Updated', 'wp-dbmanager').'</font>';
367         }
368         if(empty($text)) {
369             $text = '<font color="red">'.__('No Database Option Updated', 'wp-dbmanager').'</font>';
370         }
371         wp_clear_scheduled_hook('dbmanager_cron_backup');
372         if($backup_options['backup_period'] > 0) {
373             if (!wp_next_scheduled('dbmanager_cron_backup')) {
374                 wp_schedule_event(time(), 'dbmanager_backup', 'dbmanager_cron_backup');
375             }
376         }
377         wp_clear_scheduled_hook('dbmanager_cron_optimize');
378         if($backup_options['optimize_period'] > 0) {
379             if (!wp_next_scheduled('dbmanager_cron_optimize')) {
380                 wp_schedule_event(time(), 'dbmanager_optimize', 'dbmanager_cron_optimize');
381             }
382         }
383     }
384     $path = detect_mysql();
385 ?>
386 <script type="text/javascript">
387 /* <![CDATA[*/
388     function mysqlpath() {
389         document.getElementById('db_mysqlpath').value = '<?php echo $path['mysql']; ?>';
390     }
391     function mysqldumppath() {
392         document.getElementById('db_mysqldumppath').value = '<?php echo $path['mysqldump']; ?>';
393     }
394 /* ]]> */
395 </script>
396 <?php if(!empty($text)) { echo '<!-- Last Action --><div id="message" class="updated fade"><p>'.$text.'</p></div>'; } ?>
397 <!-- Database Options -->
398 <form action="<?php echo $_SERVER['REQUEST_URI']; ?>" method="post">
399     <div class="wrap">
400         <h2><?php _e('Database Options', 'wp-dbmanager'); ?></h2>
401         <h3><?php _e('Paths', 'wp-dbmanager'); ?></h3>
402         <table class="form-table">
403             <tr>
404                 <td width="20%" valign="top"><strong><?php _e('Path To mysqldump:', 'wp-dbmanager'); ?></strong></td>
405                 <td width="80%">
406                     <input type="text" id="db_mysqldumppath" name="db_mysqldumppath" size="60" maxlength="100" value="<?php echo stripslashes($backup_options['mysqldumppath']); ?>" />&nbsp;&nbsp;<input type="button" value="<?php _e('Auto Detect', 'wp-dbmanager'); ?>" onclick="mysqldumppath();" />
407                     <p><?php _e('The absolute path to mysqldump without trailing slash. If unsure, please email your server administrator about this.', 'wp-dbmanager'); ?></p>
408                 </td>
409             </tr>
410             <tr>
411                 <td valign="top"><strong><?php _e('Path To mysql:', 'wp-dbmanager'); ?></strong></td>
412                 <td>
413                     <input type="text" id="db_mysqlpath" name="db_mysqlpath" size="60" maxlength="100" value="<?php echo stripslashes($backup_options['mysqlpath']); ?>" />&nbsp;&nbsp;<input type="button" value="<?php _e('Auto Detect', 'wp-dbmanager'); ?>"