Index: trunk/extensions/Maintenance/Maintenance_body.php |
— | — | @@ -55,8 +55,10 @@ |
56 | 56 | //(minus the .php part... duh) |
57 | 57 | $scripts = array( |
58 | 58 | 'changePassword', 'createAndPromote', 'deleteBatch', 'deleteRevision', |
59 | | - 'initEditCount', 'initStats', 'moveBatch', 'runJobs', 'showJobs', 'stats' |
| 59 | + 'initEditCount', 'initStats', 'moveBatch', 'runJobs', 'showJobs', 'stats', |
| 60 | + 'sql', 'eval', |
60 | 61 | ); |
| 62 | + sort($scripts); |
61 | 63 | global $wgOut; |
62 | 64 | wfLoadExtensionMessages('Maintenance'); |
63 | 65 | $this->setHeaders(); |
— | — | @@ -95,6 +97,9 @@ |
96 | 98 | case 'deleteRevision': |
97 | 99 | $wgOut->addHTML('<textarea name="wpDelete" rows="25" cols="80"></textarea><br /><br />'); |
98 | 100 | break; |
| 101 | + case 'eval': |
| 102 | + $wgOut->addHTML('<textarea name="wpCode" rows="25" cols="80"></textarea><br /><br />'); |
| 103 | + break; |
99 | 104 | case 'initEditCount': |
100 | 105 | //just hit the button to start this, no additional settings are needed :) |
101 | 106 | break; |
— | — | @@ -115,6 +120,9 @@ |
116 | 121 | case 'stats': |
117 | 122 | //just hit the button to start this, no additional settings are needed :) |
118 | 123 | break; |
| 124 | + case 'sql': |
| 125 | + $wgOut->addHTML('<textarea name="wpQuery" rows="25" cols="80"></textarea><br /><br />'); |
| 126 | + break; |
119 | 127 | default: |
120 | 128 | $wgOut->addHTML('<p>'.wfMsg('maintenance-invalidtype').'</p></form>'); |
121 | 129 | return; |
— | — | @@ -126,6 +134,7 @@ |
127 | 135 | function executeScript( $type ) { |
128 | 136 | global $wgOut, $wgRequest, $wgUser; |
129 | 137 | wfLoadExtensionMessages('Maintenance'); |
| 138 | + @set_time_limit(0); //if we can, disable the time limit |
130 | 139 | $this->setHeaders(); |
131 | 140 | $title = Title::makeTitle( NS_SPECIAL, $this->getName() ); |
132 | 141 | $wgOut->addHTML('<a href="'.$title->getFullURL().'">'.wfMsg('maintenance-backlink').'</a><br />'); |
— | — | @@ -252,6 +261,24 @@ |
253 | 262 | $wgUser = $OldUser; |
254 | 263 | $wgOut->addWikiMsg( 'maintenance-success', $type ); |
255 | 264 | break; |
| 265 | + case 'eval': |
| 266 | + $temp = error_reporting( E_ALL ); |
| 267 | + ob_start(); |
| 268 | + $str = eval( $wgRequest->getText( 'wpCode', 'return;' ) ); |
| 269 | + $ext = ob_get_clean(); |
| 270 | + error_reporting( 0 ); |
| 271 | + if( $ext ) { |
| 272 | + $wgOut->addHTML( nl2br($ext) . '<hr />' ); |
| 273 | + } |
| 274 | + if( !$str ) { |
| 275 | + // do nothing |
| 276 | + } elseif( is_string( $str ) ) { |
| 277 | + $wgOut->addHTML( nl2br($str) . '<hr />' ); |
| 278 | + } else { |
| 279 | + $wgOut->addHTML( nl2br( var_export( $str, true ) ) . '<hr />' ); |
| 280 | + } |
| 281 | + $wgOut->addWikiMsg( 'maintenance-success', $type ); |
| 282 | + break; |
256 | 283 | case 'initEditCount': |
257 | 284 | global $wgDBservers; |
258 | 285 | $dbw = wfGetDB( DB_MASTER ); |
— | — | @@ -431,6 +458,53 @@ |
432 | 459 | $wgOut->addWikiText($dcache); |
433 | 460 | $wgOut->addWikiMsg( 'maintenance-success', $type ); |
434 | 461 | break; |
| 462 | + case 'sql': |
| 463 | + $db = wfGetDB( DB_MASTER ); |
| 464 | + $q = $wgRequest->getText('wpQuery', ''); |
| 465 | + $db->begin(); |
| 466 | + try { |
| 467 | + $r = $db->query( $q, 'Maintenance::sql.php' ); |
| 468 | + } catch(DBQueryError $e) { |
| 469 | + global $wgShowSQLErrors; |
| 470 | + $temp = $wgShowSQLErrors; |
| 471 | + $wgShowSQLErrors = true; |
| 472 | + $wgOut->addWikiText( '<pre style="overflow: auto">' . $e->getText() . '</pre>' ); |
| 473 | + $wgShowSQLErrors = $temp; |
| 474 | + $r = false; |
| 475 | + } |
| 476 | + if($r === true) { |
| 477 | + $wgOut->addWikiMsg( 'maintenance-sql-aff', $db->affectedRows() ); |
| 478 | + } elseif( $r instanceOf ResultWrapper ) { |
| 479 | + $res = array(); |
| 480 | + for( $i = 0; $i < $r->numRows(); $i++ ) { |
| 481 | + $row = $r->fetchRow(); |
| 482 | + $res[] = $row; |
| 483 | + foreach( $row as $key => $meh ) { |
| 484 | + $names[] = $key; |
| 485 | + } |
| 486 | + } |
| 487 | + $names = array_unique($names); |
| 488 | + $rtable = '<table class="wikitable"><tr>'; |
| 489 | + foreach($names as $name) { |
| 490 | + if( is_numeric($name) ) continue; |
| 491 | + $rtable .= '<th>' . $name . '</th>'; |
| 492 | + } |
| 493 | + $rtable .= '</tr>'; |
| 494 | + foreach( $res as $data ) { |
| 495 | + $rtable .= '<tr>'; |
| 496 | + foreach( $data as $key => $value ) { |
| 497 | + if( is_numeric($key) ) continue; |
| 498 | + $rtable .= '<td><nowiki>' . $value . '</nowiki></td>'; |
| 499 | + } |
| 500 | + $rtable .= '</tr>'; |
| 501 | + } |
| 502 | + $rtable .= '</table>'; |
| 503 | + $wgOut->addWikiMsg( 'maintenance-sql-res', $r->numRows(), $rtable ); |
| 504 | + $db->freeResult($r); |
| 505 | + } |
| 506 | + $db->commit(); |
| 507 | + $wgOut->addWikiMsg( 'maintenance-success', $type ); |
| 508 | + break; |
435 | 509 | default: |
436 | 510 | $wgOut->addHTML('<p>'.wfMsg('maintenance-invalidtype').'</p></form>'); |
437 | 511 | return; |
Index: trunk/extensions/Maintenance/Maintenance.i18n.php |
— | — | @@ -21,11 +21,13 @@ |
22 | 22 | 'maintenance-createAndPromote-desc' => 'Create a user and promote to sysop status', |
23 | 23 | 'maintenance-deleteBatch-desc' => 'Mass-delete pages', |
24 | 24 | 'maintenance-deleteRevision-desc' => 'Remove revisions from the database', |
| 25 | + 'maintenance-eval-desc' => 'Evaluate PHP code in the MediaWiki environment', |
25 | 26 | 'maintenance-initEditCount-desc' => 'Recalculate the edit counts of users', |
26 | 27 | 'maintenance-initStats-desc' => 'Recalculate site statistics', |
27 | 28 | 'maintenance-moveBatch-desc' => 'Mass-move pages', |
28 | 29 | 'maintenance-runJobs-desc' => 'Run jobs in the job queue', |
29 | 30 | 'maintenance-showJobs-desc' => 'Show a list of jobs pending in the job queue', |
| 31 | + 'maintenance-sql-desc' => 'Execute an SQL query', |
30 | 32 | 'maintenance-stats-desc' => 'Show Memcached statistics', |
31 | 33 | 'maintenance-changePassword' => "Use this form to change a user's password", |
32 | 34 | 'maintenance-createAndPromote' => 'Use this form to create a new user and promote it to sysop. |
— | — | @@ -58,6 +60,10 @@ |
59 | 61 | 'maintenance-deleted' => 'DELETED', |
60 | 62 | 'maintenance-revdelete' => 'Deleting revisions $1 from wiki $2', |
61 | 63 | 'maintenance-revnotfound' => 'Revision $1 not found!', |
| 64 | + 'maintenance-sql' => 'Use this form to execute a SQL query on the database.', |
| 65 | + 'maintenance-sql-aff' => 'Affected rows: $1', |
| 66 | + 'maintenance-sql-res' => '$1 rows returned: |
| 67 | +$2', |
62 | 68 | 'maintenance-stats-edits' => 'Number of edits: $1', |
63 | 69 | 'maintenance-stats-articles' => 'Number of pages in the main namespace: $1', |
64 | 70 | 'maintenance-stats-pages' => 'Number of pages: $1', |
— | — | @@ -86,6 +92,7 @@ |
87 | 93 | 'maintenance-memc-updates' => 'updates:', |
88 | 94 | 'maintenance-memc-uncacheable' => 'uncacheable:', |
89 | 95 | 'maintenance-memc-diffcache' => 'Diff Cache', |
| 96 | + 'maintenance-eval' => 'Use this form to evaluate PHP code in the MediaWiki environment.', |
90 | 97 | ); |
91 | 98 | |
92 | 99 | /** Message documentation (Message documentation) |
Index: trunk/extensions/Maintenance/Maintenance.php |
— | — | @@ -19,7 +19,7 @@ |
20 | 20 | $wgExtensionCredits['specialpage'][] = array( |
21 | 21 | 'name' => 'Maintenance', |
22 | 22 | 'author' => 'Ryan Schmidt', |
23 | | - 'version' => '1.0.1', |
| 23 | + 'version' => '1.0.2', |
24 | 24 | 'description' => '[[Special:Maintenance|Web interface]] for various maintenance scripts', |
25 | 25 | 'descriptionmsg' => 'maintenance-desc', |
26 | 26 | 'url' => 'http://www.mediawiki.org/wiki/Extension:Maintenance', |