65 parent::__construct(
'Export' );
66 $this->dbProvider = $dbProvider;
67 $this->wikiExporterFactory = $wikiExporterFactory;
68 $this->titleFormatter = $titleFormatter;
69 $this->linksMigration = $linksMigration;
77 $this->curonly =
true;
80 $this->templates = $request->getCheck(
'templates' );
82 $request->getIntOrNull(
'pagelink-depth' )
87 if ( $request->getCheck(
'addcat' ) ) {
88 $page = $request->getText(
'pages' );
89 $catname = $request->getText(
'catname' );
91 if ( $catname !==
'' && $catname !==
null && $catname !==
false ) {
92 $t = Title::makeTitleSafe(
NS_MAIN, $catname );
101 if ( $page !==
'' ) {
104 $page .= implode(
"\n", $catpages );
108 } elseif ( $request->getCheck(
'addns' ) &&
110 $page = $request->getText(
'pages' );
111 $nsindex = $request->getText(
'nsindex',
'' );
113 if ( strval( $nsindex ) !==
'' ) {
119 $page .=
"\n" . implode(
"\n", $nspages );
122 } elseif ( $request->getCheck(
'exportall' ) &&
133 } elseif ( $request->wasPosted() && $par ==
'' ) {
136 LoggerFactory::getInstance(
'export' )->debug(
137 'Special:Export POST, dir: [{dir}], offset: [{offset}], limit: [{limit}]', [
138 'dir' => $request->getRawVal(
'dir' ),
139 'offset' => $request->getRawVal(
'offset' ),
140 'limit' => $request->getRawVal(
'limit' ),
143 $page = $request->getText(
'pages' );
144 $this->curonly = $request->getCheck(
'curonly' );
145 $rawOffset = $request->getVal(
'offset' );
154 $limit = $request->getInt(
'limit' );
155 $dir = $request->getVal(
'dir' );
159 'limit' => $maxHistory,
161 $historyCheck = $request->getCheck(
'history' );
163 if ( $this->curonly ) {
164 $history = WikiExporter::CURRENT;
165 } elseif ( !$historyCheck ) {
166 if ( $limit > 0 && ( $maxHistory == 0 || $limit < $maxHistory ) ) {
167 $history[
'limit'] = $limit;
170 if ( $offset !==
null ) {
171 $history[
'offset'] = $offset;
174 if ( strtolower( $dir ??
'' ) ==
'desc' ) {
175 $history[
'dir'] =
'desc';
184 $page = $request->getText(
'pages', $par ??
'' );
185 $historyCheck = $request->getCheck(
'history' );
187 if ( $historyCheck ) {
188 $history = WikiExporter::FULL;
190 $history = WikiExporter::CURRENT;
200 $history = WikiExporter::CURRENT;
203 $list_authors = $request->getCheck(
'listauthors' );
205 $list_authors =
false;
214 $request->response()->header(
'Content-type: application/xml; charset=utf-8' );
215 $request->response()->header(
'X-Robots-Tag: noindex,nofollow' );
217 if ( $request->getCheck(
'wpDownload' ) ) {
221 $request->response()->header(
"Content-disposition: attachment;filename={$filename}" );
226 $this->
doExport( $page, $history, $list_authors, $exportall );
232 $out->addWikiMsg(
'exporttext' );
235 $categoryName = $request->getText(
'catname' );
240 $hideIf = $canExportAll ? [
'hide-if' => [
'===',
'exportall',
'1' ] ] : [];
244 'type' =>
'textwithbutton',
246 'horizontal-label' =>
true,
247 'label-message' =>
'export-addcattext',
248 'default' => $categoryName,
250 'buttontype' =>
'submit',
251 'buttonname' =>
'addcat',
252 'buttondefault' => $this->
msg(
'export-addcat' )->text(),
258 'type' =>
'namespaceselectwithbutton',
259 'default' => $nsindex,
260 'label-message' =>
'export-addnstext',
261 'horizontal-label' =>
true,
264 'cssclass' =>
'namespaceselector',
265 'buttontype' =>
'submit',
266 'buttonname' =>
'addns',
267 'buttondefault' => $this->
msg(
'export-addns' )->text(),
272 if ( $canExportAll ) {
276 'label-message' =>
'exportall',
277 'name' =>
'exportall',
279 'default' => $request->wasPosted() && $request->getCheck(
'exportall' ),
286 'class' => HTMLTextAreaField::class,
288 'label-message' =>
'export-manual',
299 'label-message' =>
'exportcuronly',
302 'default' => !$request->wasPosted() || $request->getCheck(
'curonly' ),
306 $out->addWikiMsg(
'exportnohistory' );
312 'label-message' =>
'export-templates',
313 'name' =>
'templates',
314 'id' =>
'wpExportTemplates',
315 'default' => $request->wasPosted() && $request->getCheck(
'templates' ),
320 $this->userCanOverrideExportDepth() ) {
322 'pagelink-depth' => [
324 'name' =>
'pagelink-depth',
325 'id' =>
'pagelink-depth',
326 'label-message' =>
'export-pagelinks',
336 'name' =>
'wpDownload',
337 'id' =>
'wpDownload',
338 'default' => !$request->wasPosted() || $request->getCheck(
'wpDownload' ),
339 'label-message' =>
'export-download',
347 'label-message' =>
'exportlistauthors',
348 'default' => $request->wasPosted() && $request->getCheck(
'listauthors' ),
349 'name' =>
'listauthors',
350 'id' =>
'listauthors',
355 $htmlForm = HTMLForm::factory(
'ooui', $formDescriptor, $this->
getContext() );
356 $htmlForm->setSubmitTextMsg(
'export-submit' );
357 $htmlForm->prepareForm()->displayForm(
false );
365 return $this->
getAuthority()->isAllowed(
'override-export-depth' );
377 protected function doExport( $page, $history, $list_authors, $exportall ) {
380 $history = WikiExporter::FULL;
385 foreach ( explode(
"\n", $page ) as $pageName ) {
386 $pageName = trim( $pageName );
387 $title = Title::newFromText( $pageName );
388 if ( $title && !$title->isExternal() && $title->getText() !==
'' ) {
390 $pageSet[$title->getPrefixedText()] =
true;
395 $inputPages = array_keys( $pageSet );
398 if ( $this->templates ) {
399 $pageSet = $this->
getTemplates( $inputPages, $pageSet );
401 $pageSet = $this->getExtraPages( $inputPages, $pageSet );
404 $pageSet = $this->
getPageLinks( $inputPages, $pageSet, $linkDepth );
407 $pages = array_keys( $pageSet );
410 foreach ( $pages as $k => $v ) {
411 $pages[$k] = str_replace(
' ',
'_', $v );
414 $pages = array_unique( $pages );
418 $db = $this->dbProvider->getReplicaDatabase();
420 $exporter = $this->wikiExporterFactory->getWikiExporter( $db, $history );
421 $exporter->list_authors = $list_authors;
422 $exporter->openStream();
425 $exporter->allPages();
428 foreach ( $pages as $page ) {
429 # T10824: Only export pages the user can read
430 $title = Title::newFromText( $page );
431 if ( $title ===
null ) {
436 if ( !$this->
getAuthority()->authorizeRead(
'read', $title ) ) {
441 $exporter->pageByTitle( $title );
445 $exporter->closeStream();
455 $name = $title->getDBkey();
457 $dbr = $this->dbProvider->getReplicaDatabase();
458 $res = $dbr->newSelectQueryBuilder()
459 ->select( [
'page_namespace',
'page_title' ] )
461 ->join(
'categorylinks',
null,
'cl_from=page_id' )
462 ->where( [
'cl_to' => $name ] )
464 ->caller( __METHOD__ )->fetchResultSet();
468 foreach ( $res as $row ) {
469 $pages[] = Title::makeName( $row->page_namespace, $row->page_title );
482 $dbr = $this->dbProvider->getReplicaDatabase();
483 $res = $dbr->newSelectQueryBuilder()
484 ->select( [
'page_namespace',
'page_title' ] )
486 ->where( [
'page_namespace' => $nsindex ] )
488 ->caller( __METHOD__ )->fetchResultSet();
492 foreach ( $res as $row ) {
493 $pages[] = Title::makeName( $row->page_namespace, $row->page_title );
506 [ $nsField, $titleField ] = $this->linksMigration->getTitleFields(
'templatelinks' );
507 $queryInfo = $this->linksMigration->getQueryInfo(
'templatelinks' );
508 return $this->
getLinks( $inputPages, $pageSet,
509 $queryInfo[
'tables'],
510 [
'namespace' => $nsField,
'title' => $titleField ],
512 [
'templatelinks' => [
'JOIN', [
'page_id=tl_from' ] ] ],
524 private function getExtraPages( $inputPages, $pageSet ) {
526 $this->
getHookRunner()->onSpecialExportGetExtraPages( $inputPages, $extraPages );
527 foreach ( $extraPages as $extraPage ) {
528 $pageSet[$this->titleFormatter->getPrefixedText( $extraPage )] =
true;
539 if ( $depth ===
null || $depth < 0 ) {
545 if ( $depth > $maxLinkDepth ) {
546 return $maxLinkDepth;
556 return intval( min( $depth, 5 ) );
567 for ( ; $depth > 0; --$depth ) {
568 [ $nsField, $titleField ] = $this->linksMigration->getTitleFields(
'pagelinks' );
569 $queryInfo = $this->linksMigration->getQueryInfo(
'pagelinks' );
571 $inputPages, $pageSet, $queryInfo[
'tables'],
572 [
'namespace' => $nsField,
'title' => $titleField ],
573 array_merge( [
'pagelinks' => [
'JOIN', [
'page_id=pl_from' ] ] ], $queryInfo[
'joins'] )
575 $inputPages = array_keys( $pageSet );
590 protected function getLinks( $inputPages, $pageSet, $table, $fields, $join ) {
591 $dbr = $this->dbProvider->getReplicaDatabase();
594 foreach ( $inputPages as $page ) {
595 $title = Title::newFromText( $page );
597 $pageSet[$title->getPrefixedText()] =
true;
600 $result = $dbr->select(
604 'page_namespace' => $title->getNamespace(),
605 'page_title' => $title->getDBkey()
612 foreach ( $result as $row ) {
613 $template = Title::makeTitle( $row->namespace, $row->title );
614 $pageSet[$template->getPrefixedText()] =
true;
630class_alias( SpecialExport::class,
'SpecialExport' );
wfTimestampNow()
Convenience function; returns MediaWiki timestamp for the present time.
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
wfResetOutputBuffers( $resetGzipEncoding=true)
Clear away any user-level output buffers, discarding contents.
A class containing constants representing the names of configuration variables.
const ExportMaxLinkDepth
Name constant for the ExportMaxLinkDepth setting, for use with Config::get()
const Sitename
Name constant for the Sitename setting, for use with Config::get()
const ExportAllowAll
Name constant for the ExportAllowAll setting, for use with Config::get()
const ExportMaxHistory
Name constant for the ExportMaxHistory setting, for use with Config::get()
const ExportAllowListContributors
Name constant for the ExportAllowListContributors setting, for use with Config::get()
const ExportPagelistLimit
Name constant for the ExportPagelistLimit setting, for use with Config::get()
const ExportFromNamespaces
Name constant for the ExportFromNamespaces setting, for use with Config::get()
const ExportAllowHistory
Name constant for the ExportAllowHistory setting, for use with Config::get()
Parent class for all special pages.
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
getConfig()
Shortcut to get main config object.
getContext()
Gets the context this SpecialPage is executed in.
getRequest()
Get the WebRequest being used for this instance.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getOutput()
Get the OutputPage being used for this instance.
getAuthority()
Shortcut to get the Authority executing this instance.
outputHeader( $summaryMessageKey='')
Outputs a summary message on top of special pages Per default the message key is the canonical name o...
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.