Merge "Throw exception in importDump instead of dumping a random backtrace and erroring"
[lhc/web/wiklou.git] / includes / Export.php
index 0ebdb78..43dfd17 100644 (file)
  * @ingroup SpecialPage Dump
  */
 class WikiExporter {
-       var $list_authors = false; # Return distinct author list (when not returning full history)
-       var $author_list = "";
+       /** @var bool Return distinct author list (when not returning full history) */
+       public $list_authors = false;
 
-       var $dumpUploads = false;
-       var $dumpUploadFileContents = false;
+       /** @var bool */
+       public $dumpUploads = false;
+
+       /** @var bool */
+       public $dumpUploadFileContents = false;
+
+       /** @var string */
+       protected $author_list = "";
 
        const FULL = 1;
        const CURRENT = 2;
@@ -49,21 +55,21 @@ class WikiExporter {
        const TEXT = 0;
        const STUB = 1;
 
-       var $buffer;
+       /** @var int */
+       protected $buffer;
 
-       var $text;
+       /** @var int */
+       protected $text;
 
-       /**
-        * @var DumpOutput
-        */
-       var $sink;
+       /** @var DumpOutput */
+       protected $sink;
 
        /**
         * Returns the export schema version.
         * @return string
         */
        public static function schemaVersion() {
-               return "0.8";
+               return "0.9";
        }
 
        /**
@@ -97,7 +103,7 @@ class WikiExporter {
         * various row objects and XML output for filtering. Filters
         * can be chained or used as callbacks.
         *
-        * @param $sink mixed
+        * @param DumpOutput $sink
         */
        public function setOutputSink( &$sink ) {
                $this->sink =& $sink;
@@ -125,7 +131,7 @@ class WikiExporter {
        /**
         * Dumps a series of page and revision records for those pages
         * in the database falling within the page_id range given.
-        * @param int $start inclusive lower limit (this id is included)
+        * @param int $start Inclusive lower limit (this id is included)
         * @param int $end Exclusive upper limit (this id is not included)
         *   If 0, no upper limit.
         */
@@ -140,7 +146,7 @@ class WikiExporter {
        /**
         * Dumps a series of page and revision records for those pages
         * in the database with revisions falling within the rev_id range given.
-        * @param int $start inclusive lower limit (this id is included)
+        * @param int $start Inclusive lower limit (this id is included)
         * @param int $end Exclusive upper limit (this id is not included)
         *   If 0, no upper limit.
         */
@@ -153,7 +159,7 @@ class WikiExporter {
        }
 
        /**
-        * @param $title Title
+        * @param Title $title
         */
        public function pageByTitle( $title ) {
                $this->dumpFrom(
@@ -162,7 +168,7 @@ class WikiExporter {
        }
 
        /**
-        * @param $name string
+        * @param string $name
         * @throws MWException
         */
        public function pageByName( $name ) {
@@ -175,7 +181,7 @@ class WikiExporter {
        }
 
        /**
-        * @param $names array
+        * @param array $names
         */
        public function pagesByName( $names ) {
                foreach ( $names as $name ) {
@@ -188,8 +194,8 @@ class WikiExporter {
        }
 
        /**
-        * @param $start int
-        * @param $end int
+        * @param int $start
+        * @param int $end
         */
        public function logsByRange( $start, $end ) {
                $condition = 'log_id >= ' . intval( $start );
@@ -204,7 +210,7 @@ class WikiExporter {
         * Not called by default (depends on $this->list_authors)
         * Can be set by Special:Export when not exporting whole history
         *
-        * @param $cond
+        * @param array $cond
         */
        protected function do_list_authors( $cond ) {
                wfProfileIn( __METHOD__ );
@@ -237,7 +243,7 @@ class WikiExporter {
        }
 
        /**
-        * @param $cond string
+        * @param string $cond
         * @throws MWException
         * @throws Exception
         */
@@ -426,7 +432,7 @@ class WikiExporter {
         * separate database connection not managed by LoadBalancer; some
         * blob storage types will make queries to pull source data.
         *
-        * @param $resultset ResultWrapper
+        * @param ResultWrapper $resultset
         */
        protected function outputPageStream( $resultset ) {
                $last = null;
@@ -461,7 +467,7 @@ class WikiExporter {
        }
 
        /**
-        * @param $resultset array
+        * @param array $resultset
         */
        protected function outputLogStream( $resultset ) {
                foreach ( $resultset as $row ) {
@@ -501,8 +507,17 @@ class XmlDumpWriter {
                return Xml::element( 'mediawiki', array(
                        'xmlns'              => "http://www.mediawiki.org/xml/export-$ver/",
                        'xmlns:xsi'          => "http://www.w3.org/2001/XMLSchema-instance",
+                       /*
+                        * When a new version of the schema is created, it needs staging on mediawiki.org.
+                        * This requires a change in the operations/mediawiki-config git repo.
+                        *
+                        * Create a changeset like https://gerrit.wikimedia.org/r/#/c/149643/ in which
+                        * you copy in the new xsd file.
+                        *
+                        * After it is reviewed, merged and deployed (sync-docroot), the index.html needs purging.
+                        * echo "http://www.mediawiki.org/xml/index.html" | mwscript purgeList.php --wiki=aawiki
+                        */
                        'xsi:schemaLocation' => "http://www.mediawiki.org/xml/export-$ver/ " .
-                               #TODO: how do we get a new version up there?
                                "http://www.mediawiki.org/xml/export-$ver.xsd",
                        'version'            => $ver,
                        'xml:lang'           => $wgLanguageCode ),
@@ -517,6 +532,7 @@ class XmlDumpWriter {
        function siteInfo() {
                $info = array(
                        $this->sitename(),
+                       $this->dbname(),
                        $this->homelink(),
                        $this->generator(),
                        $this->caseSetting(),
@@ -534,6 +550,14 @@ class XmlDumpWriter {
                return Xml::element( 'sitename', array(), $wgSitename );
        }
 
+       /**
+        * @return string
+        */
+       function dbname() {
+               global $wgDBname;
+               return Xml::element( 'dbname', array(), $wgDBname );
+       }
+
        /**
         * @return string
         */
@@ -591,7 +615,7 @@ class XmlDumpWriter {
         * Opens a "<page>" section on the output stream, with data
         * from the given database row.
         *
-        * @param $row object
+        * @param object $row
         * @return string
         */
        public function openPage( $row ) {
@@ -634,7 +658,7 @@ class XmlDumpWriter {
         * Dumps a "<revision>" section on the output stream, with
         * data filled in from the given database row.
         *
-        * @param $row object
+        * @param object $row
         * @return string
         * @access private
         */
@@ -664,12 +688,30 @@ class XmlDumpWriter {
                        $out .= "      " . Xml::elementClean( 'comment', array(), strval( $row->rev_comment ) ) . "\n";
                }
 
+               if ( isset( $row->rev_content_model ) && !is_null( $row->rev_content_model ) ) {
+                       $content_model = strval( $row->rev_content_model );
+               } else {
+                       // probably using $wgContentHandlerUseDB = false;
+                       $title = Title::makeTitle( $row->page_namespace, $row->page_title );
+                       $content_model = ContentHandler::getDefaultModelFor( $title );
+               }
+
+               $content_handler = ContentHandler::getForModelID( $content_model );
+
+               if ( isset( $row->rev_content_format ) && !is_null( $row->rev_content_format ) ) {
+                       $content_format = strval( $row->rev_content_format );
+               } else {
+                       // probably using $wgContentHandlerUseDB = false;
+                       $content_format = $content_handler->getDefaultFormat();
+               }
+
                $text = '';
                if ( isset( $row->rev_deleted ) && ( $row->rev_deleted & Revision::DELETED_TEXT ) ) {
                        $out .= "      " . Xml::element( 'text', array( 'deleted' => 'deleted' ) ) . "\n";
                } elseif ( isset( $row->old_text ) ) {
                        // Raw text from the database may have invalid chars
                        $text = strval( Revision::getRevisionText( $row ) );
+                       $text = $content_handler->exportTransform( $text, $content_format );
                        $out .= "      " . Xml::elementClean( 'text',
                                array( 'xml:space' => 'preserve', 'bytes' => intval( $row->rev_len ) ),
                                strval( $text ) ) . "\n";
@@ -689,26 +731,7 @@ class XmlDumpWriter {
                        $out .= "      <sha1/>\n";
                }
 
-               if ( isset( $row->rev_content_model ) && !is_null( $row->rev_content_model ) ) {
-                       $content_model = strval( $row->rev_content_model );
-               } else {
-                       // probably using $wgContentHandlerUseDB = false;
-                       // @todo test!
-                       $title = Title::makeTitle( $row->page_namespace, $row->page_title );
-                       $content_model = ContentHandler::getDefaultModelFor( $title );
-               }
-
                $out .= "      " . Xml::element( 'model', null, strval( $content_model ) ) . "\n";
-
-               if ( isset( $row->rev_content_format ) && !is_null( $row->rev_content_format ) ) {
-                       $content_format = strval( $row->rev_content_format );
-               } else {
-                       // probably using $wgContentHandlerUseDB = false;
-                       // @todo test!
-                       $content_handler = ContentHandler::getForModelID( $content_model );
-                       $content_format = $content_handler->getDefaultFormat();
-               }
-
                $out .= "      " . Xml::element( 'format', null, strval( $content_format ) ) . "\n";
 
                wfRunHooks( 'XmlDumpWriterWriteRevision', array( &$this, &$out, $row, $text ) );
@@ -723,7 +746,7 @@ class XmlDumpWriter {
         * Dumps a "<logitem>" section on the output stream, with
         * data filled in from the given database row.
         *
-        * @param $row object
+        * @param object $row
         * @return string
         * @access private
         */
@@ -767,7 +790,7 @@ class XmlDumpWriter {
        }
 
        /**
-        * @param $timestamp string
+        * @param string $timestamp
         * @param string $indent Default to six spaces
         * @return string
         */
@@ -777,8 +800,8 @@ class XmlDumpWriter {
        }
 
        /**
-        * @param $id
-        * @param $text string
+        * @param int $id
+        * @param string $text
         * @param string $indent Default to six spaces
         * @return string
         */
@@ -796,8 +819,8 @@ class XmlDumpWriter {
 
        /**
         * Warning! This data is potentially inconsistent. :(
-        * @param $row
-        * @param $dumpContents bool
+        * @param object $row
+        * @param bool $dumpContents
         * @return string
         */
        function writeUploads( $row, $dumpContents = false ) {
@@ -817,7 +840,7 @@ class XmlDumpWriter {
 
        /**
         * @param File $file
-        * @param $dumpContents bool
+        * @param bool $dumpContents
         * @return string
         */
        function writeUpload( $file, $dumpContents = false ) {
@@ -891,45 +914,45 @@ class XmlDumpWriter {
 class DumpOutput {
 
        /**
-        * @param $string string
+        * @param string $string
         */
        function writeOpenStream( $string ) {
                $this->write( $string );
        }
 
        /**
-        * @param $string string
+        * @param string $string
         */
        function writeCloseStream( $string ) {
                $this->write( $string );
        }
 
        /**
-        * @param $page
-        * @param $string string
+        * @param object $page
+        * @param string $string
         */
        function writeOpenPage( $page, $string ) {
                $this->write( $string );
        }
 
        /**
-        * @param $string string
+        * @param string $string
         */
        function writeClosePage( $string ) {
                $this->write( $string );
        }
 
        /**
-        * @param $rev
-        * @param $string string
+        * @param object $rev
+        * @param string $string
         */
        function writeRevision( $rev, $string ) {
                $this->write( $string );
        }
 
        /**
-        * @param $rev
-        * @param $string string
+        * @param object $rev
+        * @param string $string
         */
        function writeLogItem( $rev, $string ) {
                $this->write( $string );
@@ -937,7 +960,7 @@ class DumpOutput {
 
        /**
         * Override to write to a different stream type.
-        * @param $string string
+        * @param string $string
         * @return bool
         */
        function write( $string ) {
@@ -949,7 +972,7 @@ class DumpOutput {
         * and reopen new file with the old name. Use this
         * for writing out a file in multiple pieces
         * at specified checkpoints (e.g. every n hours).
-        * @param $newname mixed File name. May be a string or an array with one element
+        * @param string|array $newname File name. May be a string or an array with one element
         */
        function closeRenameAndReopen( $newname ) {
        }
@@ -958,7 +981,7 @@ class DumpOutput {
         * Close the old file, and move it to a specified name.
         * Use this for the last piece of a file written out
         * at specified checkpoints (e.g. every n hours).
-        * @param $newname mixed File name. May be a string or an array with one element
+        * @param string|array $newname File name. May be a string or an array with one element
         * @param bool $open If true, a new file with the old filename will be opened
         *   again for writing (default: false)
         */
@@ -983,7 +1006,7 @@ class DumpFileOutput extends DumpOutput {
        protected $handle = false, $filename;
 
        /**
-        * @param $file
+        * @param string $file
         */
        function __construct( $file ) {
                $this->handle = fopen( $file, "wt" );
@@ -991,7 +1014,7 @@ class DumpFileOutput extends DumpOutput {
        }
 
        /**
-        * @param $string string
+        * @param string $string
         */
        function writeCloseStream( $string ) {
                parent::writeCloseStream( $string );
@@ -1002,21 +1025,21 @@ class DumpFileOutput extends DumpOutput {
        }
 
        /**
-        * @param $string string
+        * @param string $string
         */
        function write( $string ) {
                fputs( $this->handle, $string );
        }
 
        /**
-        * @param $newname
+        * @param string $newname
         */
        function closeRenameAndReopen( $newname ) {
                $this->closeAndRename( $newname, true );
        }
 
        /**
-        * @param $newname
+        * @param string $newname
         * @throws MWException
         */
        function renameOrException( $newname ) {
@@ -1026,8 +1049,8 @@ class DumpFileOutput extends DumpOutput {
        }
 
        /**
-        * @param $newname array
-        * @return mixed
+        * @param array $newname
+        * @return string
         * @throws MWException
         */
        function checkRenameArgCount( $newname ) {
@@ -1042,8 +1065,8 @@ class DumpFileOutput extends DumpOutput {
        }
 
        /**
-        * @param $newname mixed
-        * @param $open bool
+        * @param string $newname
+        * @param bool $open
         */
        function closeAndRename( $newname, $open = false ) {
                $newname = $this->checkRenameArgCount( $newname );
@@ -1078,8 +1101,8 @@ class DumpPipeOutput extends DumpFileOutput {
        protected $procOpenResource = false;
 
        /**
-        * @param $command
-        * @param $file null
+        * @param string $command
+        * @param string $file
         */
        function __construct( $command, $file = null ) {
                if ( !is_null( $file ) ) {
@@ -1092,7 +1115,7 @@ class DumpPipeOutput extends DumpFileOutput {
        }
 
        /**
-        * @param $string string
+        * @param string $string
         */
        function writeCloseStream( $string ) {
                parent::writeCloseStream( $string );
@@ -1103,7 +1126,7 @@ class DumpPipeOutput extends DumpFileOutput {
        }
 
        /**
-        * @param $command
+        * @param string $command
         */
        function startCommand( $command ) {
                $spec = array(
@@ -1115,15 +1138,15 @@ class DumpPipeOutput extends DumpFileOutput {
        }
 
        /**
-        * @param mixed $newname
+        * @param string $newname
         */
        function closeRenameAndReopen( $newname ) {
                $this->closeAndRename( $newname, true );
        }
 
        /**
-        * @param $newname mixed
-        * @param $open bool
+        * @param string $newname
+        * @param bool $open
         */
        function closeAndRename( $newname, $open = false ) {
                $newname = $this->checkRenameArgCount( $newname );
@@ -1144,7 +1167,6 @@ class DumpPipeOutput extends DumpFileOutput {
                        }
                }
        }
-
 }
 
 /**
@@ -1152,9 +1174,8 @@ class DumpPipeOutput extends DumpFileOutput {
  * @ingroup Dump
  */
 class DumpGZipOutput extends DumpPipeOutput {
-
        /**
-        * @param $file string
+        * @param string $file
         */
        function __construct( $file ) {
                parent::__construct( "gzip", $file );
@@ -1166,9 +1187,8 @@ class DumpGZipOutput extends DumpPipeOutput {
  * @ingroup Dump
  */
 class DumpBZip2Output extends DumpPipeOutput {
-
        /**
-        * @param $file string
+        * @param string $file
         */
        function __construct( $file ) {
                parent::__construct( "bzip2", $file );
@@ -1180,9 +1200,8 @@ class DumpBZip2Output extends DumpPipeOutput {
  * @ingroup Dump
  */
 class Dump7ZipOutput extends DumpPipeOutput {
-
        /**
-        * @param $file string
+        * @param string $file
         */
        function __construct( $file ) {
                $command = $this->setup7zCommand( $file );
@@ -1191,7 +1210,7 @@ class Dump7ZipOutput extends DumpPipeOutput {
        }
 
        /**
-        * @param $file string
+        * @param string $file
         * @return string
         */
        function setup7zCommand( $file ) {
@@ -1203,8 +1222,8 @@ class Dump7ZipOutput extends DumpPipeOutput {
        }
 
        /**
-        * @param $newname string
-        * @param $open bool
+        * @param string $newname
+        * @param bool $open
         */
        function closeAndRename( $newname, $open = false ) {
                $newname = $this->checkRenameArgCount( $newname );
@@ -1227,7 +1246,6 @@ class Dump7ZipOutput extends DumpPipeOutput {
  * @ingroup Dump
  */
 class DumpFilter {
-
        /**
         * @var DumpOutput
         * FIXME will need to be made protected whenever legacy code
@@ -1241,29 +1259,29 @@ class DumpFilter {
        protected $sendingThisPage;
 
        /**
-        * @param $sink DumpOutput
+        * @param DumpOutput $sink
         */
        function __construct( &$sink ) {
                $this->sink =& $sink;
        }
 
        /**
-        * @param $string string
+        * @param string $string
         */
        function writeOpenStream( $string ) {
                $this->sink->writeOpenStream( $string );
        }
 
        /**
-        * @param $string string
+        * @param string $string
         */
        function writeCloseStream( $string ) {
                $this->sink->writeCloseStream( $string );
        }
 
        /**
-        * @param $page
-        * @param $string string
+        * @param object $page
+        * @param string $string
         */
        function writeOpenPage( $page, $string ) {
                $this->sendingThisPage = $this->pass( $page, $string );
@@ -1273,7 +1291,7 @@ class DumpFilter {
        }
 
        /**
-        * @param $string string
+        * @param string $string
         */
        function writeClosePage( $string ) {
                if ( $this->sendingThisPage ) {
@@ -1283,8 +1301,8 @@ class DumpFilter {
        }
 
        /**
-        * @param $rev
-        * @param $string string
+        * @param object $rev
+        * @param string $string
         */
        function writeRevision( $rev, $string ) {
                if ( $this->sendingThisPage ) {
@@ -1293,23 +1311,23 @@ class DumpFilter {
        }
 
        /**
-        * @param $rev
-        * @param $string string
+        * @param object $rev
+        * @param string $string
         */
        function writeLogItem( $rev, $string ) {
                $this->sink->writeRevision( $rev, $string );
        }
 
        /**
-        * @param $newname string
+        * @param string $newname
         */
        function closeRenameAndReopen( $newname ) {
                $this->sink->closeRenameAndReopen( $newname );
        }
 
        /**
-        * @param $newname string
-        * @param $open bool
+        * @param string $newname
+        * @param bool $open
         */
        function closeAndRename( $newname, $open = false ) {
                $this->sink->closeAndRename( $newname, $open );
@@ -1324,7 +1342,7 @@ class DumpFilter {
 
        /**
         * Override for page-based filter types.
-        * @param $page
+        * @param object $page
         * @return bool
         */
        function pass( $page ) {
@@ -1337,9 +1355,8 @@ class DumpFilter {
  * @ingroup Dump
  */
 class DumpNotalkFilter extends DumpFilter {
-
        /**
-        * @param $page
+        * @param object $page
         * @return bool
         */
        function pass( $page ) {
@@ -1352,12 +1369,15 @@ class DumpNotalkFilter extends DumpFilter {
  * @ingroup Dump
  */
 class DumpNamespaceFilter extends DumpFilter {
-       var $invert = false;
-       var $namespaces = array();
+       /** @var bool */
+       protected $invert = false;
+
+       /** @var array */
+       protected $namespaces = array();
 
        /**
-        * @param $sink DumpOutput
-        * @param $param
+        * @param DumpOutput $sink
+        * @param array $param
         * @throws MWException
         */
        function __construct( &$sink, $param ) {
@@ -1403,7 +1423,7 @@ class DumpNamespaceFilter extends DumpFilter {
        }
 
        /**
-        * @param $page
+        * @param object $page
         * @return bool
         */
        function pass( $page ) {
@@ -1417,11 +1437,17 @@ class DumpNamespaceFilter extends DumpFilter {
  * @ingroup Dump
  */
 class DumpLatestFilter extends DumpFilter {
-       var $page, $pageString, $rev, $revString;
+       protected $page;
+
+       protected $pageString;
+
+       protected $rev;
+
+       protected $revString;
 
        /**
-        * @param $page
-        * @param $string string
+        * @param object $page
+        * @param string $string
         */
        function writeOpenPage( $page, $string ) {
                $this->page = $page;
@@ -1429,7 +1455,7 @@ class DumpLatestFilter extends DumpFilter {
        }
 
        /**
-        * @param $string string
+        * @param string $string
         */
        function writeClosePage( $string ) {
                if ( $this->rev ) {
@@ -1444,8 +1470,8 @@ class DumpLatestFilter extends DumpFilter {
        }
 
        /**
-        * @param $rev
-        * @param $string string
+        * @param object $rev
+        * @param string $string
         */
        function writeRevision( $rev, $string ) {
                if ( $rev->rev_id == $this->page->page_latest ) {
@@ -1462,7 +1488,7 @@ class DumpLatestFilter extends DumpFilter {
 class DumpMultiWriter {
 
        /**
-        * @param $sinks
+        * @param array $sinks
         */
        function __construct( $sinks ) {
                $this->sinks = $sinks;
@@ -1470,7 +1496,7 @@ class DumpMultiWriter {
        }
 
        /**
-        * @param $string string
+        * @param string $string
         */
        function writeOpenStream( $string ) {
                for ( $i = 0; $i < $this->count; $i++ ) {
@@ -1479,7 +1505,7 @@ class DumpMultiWriter {
        }
 
        /**
-        * @param $string string
+        * @param string $string
         */
        function writeCloseStream( $string ) {
                for ( $i = 0; $i < $this->count; $i++ ) {
@@ -1488,8 +1514,8 @@ class DumpMultiWriter {
        }
 
        /**
-        * @param $page
-        * @param $string string
+        * @param object $page
+        * @param string $string
         */
        function writeOpenPage( $page, $string ) {
                for ( $i = 0; $i < $this->count; $i++ ) {
@@ -1498,7 +1524,7 @@ class DumpMultiWriter {
        }
 
        /**
-        * @param $string
+        * @param string $string
         */
        function writeClosePage( $string ) {
                for ( $i = 0; $i < $this->count; $i++ ) {
@@ -1507,8 +1533,8 @@ class DumpMultiWriter {
        }
 
        /**
-        * @param $rev
-        * @param $string
+        * @param object $rev
+        * @param string $string
         */
        function writeRevision( $rev, $string ) {
                for ( $i = 0; $i < $this->count; $i++ ) {
@@ -1517,14 +1543,14 @@ class DumpMultiWriter {
        }
 
        /**
-        * @param $newnames
+        * @param array $newnames
         */
        function closeRenameAndReopen( $newnames ) {
                $this->closeAndRename( $newnames, true );
        }
 
        /**
-        * @param $newnames array
+        * @param array $newnames
         * @param bool $open
         */
        function closeAndRename( $newnames, $open = false ) {
@@ -1543,24 +1569,4 @@ class DumpMultiWriter {
                }
                return $filenames;
        }
-
-}
-
-/**
- * @param $string string
- * @return string
- */
-function xmlsafe( $string ) {
-       wfProfileIn( __FUNCTION__ );
-
-       /**
-        * The page may contain old data which has not been properly normalized.
-        * Invalid UTF-8 sequences or forbidden control characters will make our
-        * XML output invalid, so be sure to strip them out.
-        */
-       $string = UtfNormal::cleanUp( $string );
-
-       $string = htmlspecialchars( $string );
-       wfProfileOut( __FUNCTION__ );
-       return $string;
 }