95 $buffer = self::BUFFER, $text = self::TEXT ) {
112 $this->sink =&
$sink;
117 $this->sink->writeOpenStream(
$output );
122 $this->sink->writeCloseStream(
$output );
144 $condition =
'rev_page >= ' . intval( $start );
146 $condition .=
' AND rev_page < ' . intval( $end );
149 $condition =
'page_id >= ' . intval( $start );
151 $condition .=
' AND page_id < ' . intval( $end );
154 $this->
dumpFrom( $condition, $orderRevs );
165 $condition =
'rev_id >= ' . intval( $start );
167 $condition .=
' AND rev_id < ' . intval( $end );
177 'page_namespace=' . $title->getNamespace() .
178 ' AND page_title=' . $this->db->addQuotes( $title->getDBkey() ) );
186 $title = Title::newFromText( $name );
187 if ( is_null( $title ) ) {
188 throw new MWException(
"Can't export invalid title" );
198 foreach ( $names as $name ) {
212 $condition =
'log_id >= ' . intval( $start );
214 $condition .=
' AND log_id < ' . intval( $end );
227 $this->author_list =
"<contributors>";
230 $revQuery = Revision::getQueryInfo( [
'page' ] );
231 $res = $this->db->select(
234 'rev_user_text' =>
$revQuery[
'fields'][
'rev_user_text'],
235 'rev_user' =>
$revQuery[
'fields'][
'rev_user'],
238 $this->db->bitAnd(
'rev_deleted', Revision::DELETED_USER ) .
' = 0',
246 foreach (
$res as $row ) {
247 $this->author_list .=
"<contributor>" .
249 htmlentities( $row->rev_user_text ) .
256 $this->author_list .=
"</contributors>";
265 protected function dumpFrom( $cond =
'', $orderRevs =
false ) {
266 # For logging dumps...
267 if ( $this->
history & self::LOGS ) {
272 $where[] = $hideLogs;
274 # Add on any caller specified conditions
278 # Get logging table name for logging.* clause
279 $logging = $this->db->tableName(
'logging' );
281 if ( $this->buffer == self::STREAM ) {
282 $prev = $this->db->bufferResults(
false );
286 $commentQuery = CommentStore::getStore()->getJoin(
'log_comment' );
287 $actorQuery = ActorMigration::newMigration()->getJoin(
'log_user' );
290 $result = $this->db->select(
291 array_merge( [
'logging' ], $commentQuery[
'tables'], $actorQuery[
'tables'], [
'user' ] ),
292 [
"{$logging}.*",
'user_name' ] + $commentQuery[
'fields'] + $actorQuery[
'fields'],
295 [
'ORDER BY' =>
'log_id',
'USE INDEX' => [
'logging' =>
'PRIMARY' ] ],
297 'user' => [
'JOIN',
'user_id = ' . $actorQuery[
'fields'][
'log_user'] ]
298 ] + $commentQuery[
'joins'] + $actorQuery[
'joins']
301 if ( $this->buffer == self::STREAM ) {
302 $this->db->bufferResults( $prev );
304 }
catch ( Exception
$e ) {
313 }
catch ( Exception $e2 ) {
320 if ( $this->buffer == self::STREAM ) {
321 $this->db->bufferResults( $prev );
323 }
catch ( Exception $e2 ) {
333 $revOpts = [
'page' ];
334 if ( $this->text != self::STUB ) {
337 $revQuery = Revision::getQueryInfo( $revOpts );
340 $tables = array_merge( [
'page' ], array_diff(
$revQuery[
'tables'], [
'page' ] ) );
344 unset( $join[
'page'] );
346 $fields = array_merge(
$revQuery[
'fields'], [
'page_restrictions' ] );
349 if ( $cond !==
'' ) {
352 $opts = [
'ORDER BY' =>
'page_id ASC' ];
353 $opts[
'USE INDEX'] = [];
354 if ( is_array( $this->
history ) ) {
355 # Time offset/limit for all pages/history...
357 if ( $this->
history[
'dir'] ==
'asc' ) {
359 $opts[
'ORDER BY'] =
'rev_timestamp ASC';
362 $opts[
'ORDER BY'] =
'rev_timestamp DESC';
365 if ( !empty( $this->
history[
'offset'] ) ) {
366 $conds[] =
"rev_timestamp $op " .
367 $this->db->addQuotes( $this->db->timestamp( $this->history[
'offset'] ) );
370 if ( !empty( $this->
history[
'limit'] ) ) {
371 $opts[
'LIMIT'] = intval( $this->
history[
'limit'] );
373 } elseif ( $this->
history & self::FULL ) {
374 # Full history dumps...
375 # query optimization for history stub dumps
376 if ( $this->text == self::STUB && $orderRevs ) {
378 $opts[
'ORDER BY'] = [
'rev_page ASC',
'rev_id ASC' ];
379 $opts[
'USE INDEX'][
'revision'] =
'rev_page_id';
380 unset( $join[
'revision'] );
381 $join[
'page'] = [
'INNER JOIN',
'rev_page=page_id' ];
383 } elseif ( $this->
history & self::CURRENT ) {
384 # Latest revision dumps...
385 if ( $this->list_authors && $cond !=
'' ) {
388 $join[
'revision'] = [
'INNER JOIN',
'page_id=rev_page AND page_latest=rev_id' ];
389 } elseif ( $this->
history & self::STABLE ) {
390 # "Stable" revision dumps...
391 # Default JOIN, to be overridden...
392 $join[
'revision'] = [
'INNER JOIN',
'page_id=rev_page AND page_latest=rev_id' ];
393 # One, and only one hook should set this, and return false
394 if ( Hooks::run(
'WikiExporter::dumpStableQuery', [ &
$tables, &$opts, &$join ] ) ) {
395 throw new MWException( __METHOD__ .
" given invalid history dump type." );
397 } elseif ( $this->
history & self::RANGE ) {
398 # Dump of revisions within a specified range
399 $opts[
'ORDER BY'] = [
'rev_page ASC',
'rev_id ASC' ];
401 # Unknown history specification parameter?
402 throw new MWException( __METHOD__ .
" given invalid history dump type." );
405 if ( $this->buffer == self::STREAM ) {
406 $prev = $this->db->bufferResults(
false );
410 Hooks::run(
'ModifyExportQuery',
411 [ $this->db, &
$tables, &$cond, &$opts, &$join ] );
414 $result = $this->db->select(
422 # Output dump results
425 if ( $this->buffer == self::STREAM ) {
426 $this->db->bufferResults( $prev );
428 }
catch ( Exception
$e ) {
437 }
catch ( Exception $e2 ) {
444 if ( $this->buffer == self::STREAM ) {
445 $this->db->bufferResults( $prev );
447 }
catch ( Exception $e2 ) {
472 foreach ( $resultset as $row ) {
473 if (
$last ===
null ||
474 $last->page_namespace != $row->page_namespace ||
475 $last->page_title != $row->page_title ) {
476 if (
$last !==
null ) {
478 if ( $this->dumpUploads ) {
482 $this->sink->writeClosePage(
$output );
485 $this->sink->writeOpenPage( $row,
$output );
489 $this->sink->writeRevision( $row,
$output );
491 if (
$last !==
null ) {
493 if ( $this->dumpUploads ) {
498 $this->sink->writeClosePage(
$output );
506 foreach ( $resultset as $row ) {
508 $this->sink->writeLogItem( $row,
$output );
static getExcludeClause( $db, $audience='public', User $user=null)
SQL clause to skip forbidden log types for this user.
revsByRange( $start, $end)
Dumps a series of page and revision records for those pages in the database with revisions falling wi...
dumpFrom( $cond='', $orderRevs=false)
setOutputSink(&$sink)
Set the DumpOutput or DumpFilter object which will receive various row objects and XML output for fil...
pagesByRange( $start, $end, $orderRevs)
Dumps a series of page and revision records for those pages in the database falling within the page_i...
bool $dumpUploadFileContents
outputPageStream( $resultset)
Runs through a query result set dumping page and revision records.
allPages()
Dumps a series of page and revision records for all pages in the database, either including complete ...
logsByRange( $start, $end)
do_list_authors( $cond)
Generates the distinct list of authors of an article Not called by default (depends on $this->list_au...
outputLogStream( $resultset)
static schemaVersion()
Returns the export schema version.
__construct( $db, $history=self::CURRENT, $buffer=self::BUFFER, $text=self::TEXT)
If using WikiExporter::STREAM to stream a large amount of data, provide a database connection which i...
bool $list_authors
Return distinct author list (when not returning full history)
static configuration should be added through ResourceLoaderGetConfigVars instead can be used to get the real title after the basic globals have been set but before ordinary actions take place $output
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist Do not use this to implement individual filters if they are compatible with the ChangesListFilter and ChangesListFilterGroup structure use sub classes of those in conjunction with the ChangesListSpecialPageStructuredFilters hook This hook can be used to implement filters that do not implement that or custom behavior that is not an individual filter e g Watchlist & $tables
presenting them properly to the user as errors is done by the caller return true use this to change the list i e etc next in line in page history
returning false will NOT prevent logging $e