Index: trunk/phase3/maintenance/backup.inc |
— | — | @@ -175,7 +175,7 @@ |
176 | 176 | // extension point for subclasses to add options |
177 | 177 | } |
178 | 178 | |
179 | | - function dump( $history, $text = MW_EXPORT_TEXT ) { |
| 179 | + function dump( $history, $text = WikiExporter::TEXT ) { |
180 | 180 | # Notice messages will foul up your XML output even if they're |
181 | 181 | # relatively harmless. |
182 | 182 | if( ini_get( 'display_errors' ) ) |
— | — | @@ -192,13 +192,21 @@ |
193 | 193 | |
194 | 194 | if( !$this->skipHeader ) |
195 | 195 | $exporter->openStream(); |
196 | | - |
197 | | - if( is_null( $this->pages ) ) { |
| 196 | + # Log item dumps: all or by range |
| 197 | + if( $history & WikiExporter::LOGS ) { |
198 | 198 | if( $this->startId || $this->endId ) { |
| 199 | + $exporter->logsByRange( $this->startId, $this->endId ); |
| 200 | + } else { |
| 201 | + $exporter->allLogs(); |
| 202 | + } |
| 203 | + # Page dumps: all or by page ID range |
| 204 | + } else if( is_null( $this->pages ) ) { |
| 205 | + if( $this->startId || $this->endId ) { |
199 | 206 | $exporter->pagesByRange( $this->startId, $this->endId ); |
200 | 207 | } else { |
201 | 208 | $exporter->allPages(); |
202 | 209 | } |
| 210 | + # Dump of specific pages |
203 | 211 | } else { |
204 | 212 | $exporter->pagesByName( $this->pages ); |
205 | 213 | } |
Index: trunk/phase3/maintenance/dumpBackup.php |
— | — | @@ -63,6 +63,8 @@ |
64 | 64 | $dumper->dump( WikiExporter::FULL, $textMode ); |
65 | 65 | } elseif( isset( $options['current'] ) ) { |
66 | 66 | $dumper->dump( WikiExporter::CURRENT, $textMode ); |
| 67 | +} elseif( isset( $options['logs'] ) ) { |
| 68 | + $dumper->dump( WikiExporter::LOGS ); |
67 | 69 | } else { |
68 | 70 | $dumper->progress( <<<ENDS |
69 | 71 | This script dumps the wiki page database into an XML interchange wrapper |
— | — | @@ -74,6 +76,7 @@ |
75 | 77 | Actions: |
76 | 78 | --full Dump complete history of every page. |
77 | 79 | --current Includes only the latest revision of each page. |
| 80 | + --logs Dump action logs for every page. |
78 | 81 | |
79 | 82 | Options: |
80 | 83 | --quiet Don't dump status reports to stderr. |
Index: trunk/phase3/includes/Export.php |
— | — | @@ -32,6 +32,7 @@ |
33 | 33 | |
34 | 34 | const FULL = 0; |
35 | 35 | const CURRENT = 1; |
| 36 | + const LOGS = 2; |
36 | 37 | |
37 | 38 | const BUFFER = 0; |
38 | 39 | const STREAM = 1; |
— | — | @@ -108,6 +109,18 @@ |
109 | 110 | } |
110 | 111 | return $this->dumpFrom( $condition ); |
111 | 112 | } |
| 113 | + |
| 114 | + function allLogs() { |
| 115 | + return $this->dumpFrom( '' ); |
| 116 | + } |
| 117 | + |
| 118 | + function logsByRange( $start, $end ) { |
| 119 | + $condition = 'log_id >= ' . intval( $start ); |
| 120 | + if( $end ) { |
| 121 | + $condition .= ' AND log_id < ' . intval( $end ); |
| 122 | + } |
| 123 | + return $this->dumpFrom( $condition ); |
| 124 | + } |
112 | 125 | |
113 | 126 | /** |
114 | 127 | * @param $title Title |
— | — | @@ -166,7 +179,25 @@ |
167 | 180 | function dumpFrom( $cond = '' ) { |
168 | 181 | $fname = 'WikiExporter::dumpFrom'; |
169 | 182 | wfProfileIn( $fname ); |
170 | | - |
| 183 | + |
| 184 | + # For logs dumps... |
| 185 | + if( $this->history & self::LOGS ) { |
| 186 | + $where = array( 'user_id = log_user' ); |
| 187 | + # Hide private logs |
| 188 | + $where[] = LogEventsList::getExcludeClause( $this->db ); |
| 189 | + if( $cond ) $where[] = $cond; |
| 190 | + $result = $this->db->select( array('logging','user'), |
| 191 | + '*', |
| 192 | + $where, |
| 193 | + $fname, |
| 194 | + array( 'ORDER BY' => 'log_id') |
| 195 | + ); |
| 196 | + $wrapper = $this->db->resultObject( $result ); |
| 197 | + $this->outputLogStream( $wrapper ); |
| 198 | + wfProfileOut( $fname ); |
| 199 | + return; |
| 200 | + } |
| 201 | + # For page dumps... |
171 | 202 | $page = $this->db->tableName( 'page' ); |
172 | 203 | $revision = $this->db->tableName( 'revision' ); |
173 | 204 | $text = $this->db->tableName( 'text' ); |
— | — | @@ -234,10 +265,10 @@ |
235 | 266 | } |
236 | 267 | $result = $this->db->query( $sql, $fname ); |
237 | 268 | $wrapper = $this->db->resultObject( $result ); |
238 | | - $this->outputStream( $wrapper ); |
| 269 | + $this->outputPageStream( $wrapper ); |
239 | 270 | |
240 | 271 | if ( $this->list_authors ) { |
241 | | - $this->outputStream( $wrapper ); |
| 272 | + $this->outputPageStream( $wrapper ); |
242 | 273 | } |
243 | 274 | |
244 | 275 | if( $this->buffer == WikiExporter::STREAM ) { |
— | — | @@ -260,7 +291,7 @@ |
261 | 292 | * @param $resultset ResultWrapper |
262 | 293 | * @access private |
263 | 294 | */ |
264 | | - function outputStream( $resultset ) { |
| 295 | + function outputPageStream( $resultset ) { |
265 | 296 | $last = null; |
266 | 297 | while( $row = $resultset->fetchObject() ) { |
267 | 298 | if( is_null( $last ) || |
— | — | @@ -292,6 +323,14 @@ |
293 | 324 | } |
294 | 325 | $resultset->free(); |
295 | 326 | } |
| 327 | + |
| 328 | + function outputLogStream( $resultset ) { |
| 329 | + while( $row = $resultset->fetchObject() ) { |
| 330 | + $output = $this->writer->writeLogItem( $row ); |
| 331 | + $this->sink->writeLogItem( $row, $output ); |
| 332 | + } |
| 333 | + $resultset->free(); |
| 334 | + } |
296 | 335 | } |
297 | 336 | |
298 | 337 | /** |
— | — | @@ -465,7 +504,55 @@ |
466 | 505 | wfProfileOut( $fname ); |
467 | 506 | return $out; |
468 | 507 | } |
| 508 | + |
| 509 | + /** |
| 510 | + * Dumps a <logitem> section on the output stream, with |
| 511 | + * data filled in from the given database row. |
| 512 | + * |
| 513 | + * @param $row object |
| 514 | + * @return string |
| 515 | + * @access private |
| 516 | + */ |
| 517 | + function writeLogItem( $row ) { |
| 518 | + $fname = 'WikiExporter::writeLogItem'; |
| 519 | + wfProfileIn( $fname ); |
469 | 520 | |
| 521 | + $out = " <logitem>\n"; |
| 522 | + $out .= " " . wfElement( 'id', null, strval( $row->log_id ) ) . "\n"; |
| 523 | + |
| 524 | + $out .= $this->writeTimestamp( $row->log_timestamp ); |
| 525 | + |
| 526 | + if( $row->log_deleted & LogPage::DELETED_USER ) { |
| 527 | + $out .= " " . wfElement( 'contributor', array( 'deleted' => 'deleted' ) ) . "\n"; |
| 528 | + } else { |
| 529 | + $out .= $this->writeContributor( $row->log_user, $row->user_name ); |
| 530 | + } |
| 531 | + |
| 532 | + if( $row->log_deleted & LogPage::DELETED_COMMENT ) { |
| 533 | + $out .= " " . wfElement( 'comment', array( 'deleted' => 'deleted' ) ) . "\n"; |
| 534 | + } elseif( $row->log_comment != '' ) { |
| 535 | + $out .= " " . wfElementClean( 'comment', null, strval( $row->log_comment ) ) . "\n"; |
| 536 | + } |
| 537 | + |
| 538 | + $out .= " " . wfElement( 'type', null, strval( $row->log_type ) ) . "\n"; |
| 539 | + $out .= " " . wfElement( 'action', null, strval( $row->log_action ) ) . "\n"; |
| 540 | + |
| 541 | + if( $row->log_deleted & LogPage::DELETED_ACTION ) { |
| 542 | + $out .= " " . wfElement( 'text', array( 'deleted' => 'deleted' ) ) . "\n"; |
| 543 | + } else { |
| 544 | + $title = Title::makeTitle( $row->log_namespace, $row->log_title ); |
| 545 | + $out .= " " . wfElementClean( 'title', null, $title->getPrefixedText() ) . "\n"; |
| 546 | + $out .= " " . wfElementClean( 'params', |
| 547 | + array( 'xml:space' => 'preserve' ), |
| 548 | + strval( $row->log_params ) ) . "\n"; |
| 549 | + } |
| 550 | + |
| 551 | + $out .= " </logitem>\n"; |
| 552 | + |
| 553 | + wfProfileOut( $fname ); |
| 554 | + return $out; |
| 555 | + } |
| 556 | + |
470 | 557 | function writeTimestamp( $timestamp ) { |
471 | 558 | $ts = wfTimestamp( TS_ISO_8601, $timestamp ); |
472 | 559 | return " " . wfElement( 'timestamp', null, $ts ) . "\n"; |
— | — | @@ -539,6 +626,10 @@ |
540 | 627 | function writeRevision( $rev, $string ) { |
541 | 628 | $this->write( $string ); |
542 | 629 | } |
| 630 | + |
| 631 | + function writeLogItem( $rev, $string ) { |
| 632 | + $this->write( $string ); |
| 633 | + } |
543 | 634 | |
544 | 635 | /** |
545 | 636 | * Override to write to a different stream type. |
— | — | @@ -654,6 +745,10 @@ |
655 | 746 | $this->sink->writeRevision( $rev, $string ); |
656 | 747 | } |
657 | 748 | } |
| 749 | + |
| 750 | + function writeLogItem( $rev, $string ) { |
| 751 | + $this->sink->writeRevision( $rev, $string ); |
| 752 | + } |
658 | 753 | |
659 | 754 | /** |
660 | 755 | * Override for page-based filter types. |