* addressed r53282#c3209 moved conditional inclusion of $wgExtensionMessages in mwScr...
[lhc/web/wiklou.git] / includes / Export.php
index faa11f0..3372cec 100644 (file)
@@ -30,9 +30,10 @@ class WikiExporter {
 
        var $dumpUploads = false;
 
-       const FULL = 0;
-       const CURRENT = 1;
-       const LOGS = 2;
+       const FULL = 1;
+       const CURRENT = 2;
+       const STABLE = 4; // extension defined
+       const LOGS = 8;
 
        const BUFFER = 0;
        const STREAM = 1;
@@ -154,7 +155,7 @@ class WikiExporter {
                wfProfileIn( $fname );
                $this->author_list = "<contributors>";
                //rev_deleted
-               $nothidden = '(rev_deleted & '.Revision::DELETED_USER.') = 0';
+               $nothidden = '('.$this->db->bitAnd('rev_deleted', Revision::DELETED_USER) . ') = 0';
 
                $sql = "SELECT DISTINCT rev_user_text,rev_user FROM {$page},{$revision} 
                WHERE page_id=rev_page AND $nothidden AND " . $cond ;
@@ -175,95 +176,103 @@ class WikiExporter {
        }
 
        protected function dumpFrom( $cond = '' ) {
-               $fname = 'WikiExporter::dumpFrom';
-               wfProfileIn( $fname );
-               
-               # For logs dumps...
+               wfProfileIn( __METHOD__ );
+               # For logging dumps...
                if( $this->history & self::LOGS ) {
+                       if( $this->buffer == WikiExporter::STREAM ) {
+                               $prev = $this->db->bufferResults( false );
+                       }
                        $where = array( 'user_id = log_user' );
                        # Hide private logs
-                       $where[] = LogEventsList::getExcludeClause( $this->db );
+                       $hideLogs = LogEventsList::getExcludeClause( $this->db );
+                       if( $hideLogs ) $where[] = $hideLogs;
+                       # Add on any caller specified conditions
                        if( $cond ) $where[] = $cond;
                        # Get logging table name for logging.* clause
                        $logging = $this->db->tableName('logging');
                        $result = $this->db->select( array('logging','user'), 
                                array( "{$logging}.*", 'user_name' ), // grab the user name
                                $where,
-                               $fname,
+                               __METHOD__,
                                array( 'ORDER BY' => 'log_id', 'USE INDEX' => array('logging' => 'PRIMARY') )
                        );
                        $wrapper = $this->db->resultObject( $result );
                        $this->outputLogStream( $wrapper );
+                       if( $this->buffer == WikiExporter::STREAM ) {
+                               $this->db->bufferResults( $prev );
+                       }
                # For page dumps...
                } else {
-                       list($page,$revision,$text) = $this->db->tableNamesN('page','revision','text');
-
-                       $order = 'ORDER BY page_id';
-                       $limit = '';
-
-                       if( $this->history == WikiExporter::FULL ) {
-                               $join = 'page_id=rev_page';
-                       } elseif( $this->history == WikiExporter::CURRENT ) {
-                               if ( $this->list_authors && $cond != '' )  { // List authors, if so desired
-                                       $this->do_list_authors ( $page , $revision , $cond );
+                       $tables = array( 'page', 'revision' );
+                       $opts = array( 'ORDER BY' => 'page_id ASC' );
+                       $opts['USE INDEX'] = array();
+                       $join = array();
+                       # Full history dumps...
+                       if( $this->history & WikiExporter::FULL ) {
+                               $join['revision'] = array('INNER JOIN','page_id=rev_page');
+                       # Latest revision dumps...
+                       } elseif( $this->history & WikiExporter::CURRENT ) {
+                               if( $this->list_authors && $cond != '' )  { // List authors, if so desired
+                                       list($page,$revision) = $this->db->tableNamesN('page','revision');
+                                       $this->do_list_authors( $page, $revision, $cond );
+                               }
+                               $join['revision'] = array('INNER JOIN','page_id=rev_page AND page_latest=rev_id');
+                       # "Stable" revision dumps...
+                       } elseif( $this->history & WikiExporter::STABLE ) {
+                               # Default JOIN, to be overridden...
+                               $join['revision'] = array('INNER JOIN','page_id=rev_page AND page_latest=rev_id');
+                               # One, and only one hook should set this, and return false
+                               if( wfRunHooks( 'WikiExporter::dumpStableQuery', array(&$tables,&$opts,&$join) ) ) {
+                                       wfProfileOut( __METHOD__ );
+                                       return new WikiError( __METHOD__." given invalid history dump type." );
                                }
-                               $join = 'page_id=rev_page AND page_latest=rev_id';
-                       } elseif ( is_array( $this->history ) ) {
-                               $join = 'page_id=rev_page';
-                               if ( $this->history['dir'] == 'asc' ) {
+                       # Time offset/limit for all pages/history...
+                       } elseif( is_array( $this->history ) ) {
+                               $revJoin = 'page_id=rev_page';
+                               # Set time order
+                               if( $this->history['dir'] == 'asc' ) {
                                        $op = '>';
-                                       $order .= ', rev_timestamp';
+                                       $opts['ORDER BY'] = 'rev_timestamp ASC';
                                } else {
                                        $op = '<';
-                                       $order .= ', rev_timestamp DESC';
+                                       $opts['ORDER BY'] = 'rev_timestamp DESC';
                                }
-                               if ( !empty( $this->history['offset'] ) ) {
-                                       $join .= " AND rev_timestamp $op " . $this->db->addQuotes(
-                                               $this->db->timestamp( $this->history['offset'] ) );
+                               # Set offset
+                               if( !empty( $this->history['offset'] ) ) {
+                                       $revJoin .= " AND rev_timestamp $op " .
+                                               $this->db->addQuotes( $this->db->timestamp( $this->history['offset'] ) );
                                }
-                               if ( !empty( $this->history['limit'] ) ) {
-                                       $limitNum = intval( $this->history['limit'] );
-                                       if ( $limitNum > 0 ) {
-                                               $limit = "LIMIT $limitNum";
-                                       }
+                               $join['revision'] = array('INNER JOIN',$revJoin);
+                               # Set query limit
+                               if( !empty( $this->history['limit'] ) ) {
+                                       $opts['LIMIT'] = intval( $this->history['limit'] );
                                }
+                       # Uknown history specification parameter?
                        } else {
-                               wfProfileOut( $fname );
-                               return new WikiError( "$fname given invalid history dump type." );
+                               wfProfileOut( __METHOD__ );
+                               return new WikiError( __METHOD__." given invalid history dump type." );
+                       }
+                       # Query optimization hacks
+                       if( $cond == '' ) {
+                               $opts[] = 'STRAIGHT_JOIN';
+                               $opts['USE INDEX']['page'] = 'PRIMARY';
+                       }
+                       # Build text join options
+                       if( $this->text != WikiExporter::STUB ) { // 1-pass
+                               $tables[] = 'text';
+                               $join['text'] = array('INNER JOIN','rev_text_id=old_id');
                        }
-                       $where = ( $cond == '' ) ? '' : "$cond AND";
 
                        if( $this->buffer == WikiExporter::STREAM ) {
                                $prev = $this->db->bufferResults( false );
                        }
-                       if( $cond == '' ) {
-                               // Optimization hack for full-database dump
-                               $revindex = $pageindex = $this->db->useIndexClause("PRIMARY");
-                               $straight = ' /*! STRAIGHT_JOIN */ ';
-                       } else {
-                               $pageindex = '';
-                               $revindex = '';
-                               $straight = '';
-                       }
-                       if( $this->text == WikiExporter::STUB ) {
-                               $sql = "SELECT $straight * FROM
-                                       $page $pageindex,
-                                       $revision $revindex
-                                       WHERE $where $join
-                                       $order $limit";
-                       } else {
-                               $sql = "SELECT $straight * FROM
-                                       $page $pageindex,
-                                       $revision $revindex,
-                                       $text
-                                       WHERE $where $join AND rev_text_id=old_id
-                                       $order $limit";
-                       }
-                       $result = $this->db->query( $sql, $fname );
+
+                       # Do the query!
+                       $result = $this->db->select( $tables, '*', $cond, __METHOD__, $opts, $join );
                        $wrapper = $this->db->resultObject( $result );
+                       # Output dump results
                        $this->outputPageStream( $wrapper );
-
-                       if ( $this->list_authors ) {
+                       if( $this->list_authors ) {
                                $this->outputPageStream( $wrapper );
                        }
 
@@ -271,7 +280,7 @@ class WikiExporter {
                                $this->db->bufferResults( $prev );
                        }
                }
-               wfProfileOut( $fname );
+               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -316,7 +325,6 @@ class WikiExporter {
                        $output .= $this->writer->closePage();
                        $this->sink->writeClosePage( $output );
                }
-               $resultset->free();
        }
        
        protected function outputLogStream( $resultset ) {
@@ -324,7 +332,6 @@ class WikiExporter {
                        $output = $this->writer->writeLogItem( $row );
                        $this->sink->writeLogItem( $row, $output );
                }
-               $resultset->free();
        }
 }
 
@@ -431,6 +438,9 @@ class XmlDumpWriter {
                $title = Title::makeTitle( $row->page_namespace, $row->page_title );
                $out .= '    ' . Xml::elementClean( 'title', array(), $title->getPrefixedText() ) . "\n";
                $out .= '    ' . Xml::element( 'id', array(), strval( $row->page_id ) ) . "\n";
+               if( $row->page_is_redirect ) {
+                       $out .= '    ' . Xml::element( 'redirect', array() ). "\n";
+               }
                if( '' != $row->page_restrictions ) {
                        $out .= '    ' . Xml::element( 'restrictions', array(),
                                strval( $row->page_restrictions ) ) . "\n";