83 [ SpecialAncientPages::class,
'Ancientpages' ],
84 [ SpecialBrokenRedirects::class,
'BrokenRedirects' ],
85 [ SpecialDeadendPages::class,
'Deadendpages' ],
86 [ SpecialDoubleRedirects::class,
'DoubleRedirects' ],
87 [ SpecialFileDuplicateSearch::class,
'FileDuplicateSearch' ],
88 [ SpecialListDuplicatedFiles::class,
'ListDuplicatedFiles' ],
89 [ SpecialLinkSearch::class,
'LinkSearch' ],
90 [ SpecialListRedirects::class,
'Listredirects' ],
91 [ SpecialLonelyPages::class,
'Lonelypages' ],
92 [ SpecialLongPages::class,
'Longpages' ],
93 [ SpecialMediaStatistics::class,
'MediaStatistics' ],
94 [ SpecialMIMESearch::class,
'MIMEsearch' ],
95 [ SpecialMostCategories::class,
'Mostcategories' ],
96 [ MostimagesPage::class,
'Mostimages' ],
97 [ SpecialMostInterwikis::class,
'Mostinterwikis' ],
98 [ SpecialMostLinkedCategories::class,
'Mostlinkedcategories' ],
99 [ SpecialMostLinkedTemplates::class,
'Mostlinkedtemplates' ],
100 [ SpecialMostLinked::class,
'Mostlinked' ],
101 [ SpecialMostRevisions::class,
'Mostrevisions' ],
102 [ SpecialFewestRevisions::class,
'Fewestrevisions' ],
103 [ SpecialShortPages::class,
'Shortpages' ],
104 [ SpecialUncategorizedCategories::class,
'Uncategorizedcategories' ],
105 [ SpecialUncategorizedPages::class,
'Uncategorizedpages' ],
106 [ SpecialUncategorizedImages::class,
'Uncategorizedimages' ],
107 [ SpecialUncategorizedTemplates::class,
'Uncategorizedtemplates' ],
108 [ SpecialUnusedCategories::class,
'Unusedcategories' ],
109 [ SpecialUnusedImages::class,
'Unusedimages' ],
110 [ SpecialWantedCategories::class,
'Wantedcategories' ],
111 [ WantedFilesPage::class,
'Wantedfiles' ],
112 [ WantedPagesPage::class,
'Wantedpages' ],
113 [ SpecialWantedTemplates::class,
'Wantedtemplates' ],
114 [ SpecialUnwatchedPages::class,
'Unwatchedpages' ],
115 [ SpecialUnusedTemplates::class,
'Unusedtemplates' ],
116 [ SpecialWithoutInterwiki::class,
'Withoutinterwiki' ],
118 Hooks::runner()->onWgQueryPages( $qp );
130 $disableQueryPageUpdate = $config->
get(
'DisableQueryPageUpdate' );
132 if ( !is_array( $disableQueryPageUpdate ) ) {
137 foreach ( $disableQueryPageUpdate as $name => $runMode ) {
138 if ( is_int( $name ) ) {
140 $pages[$runMode] =
'disabled';
142 $pages[$name] = $runMode;
154 $this->listoutput = $bool;
196 throw new MWException(
"Bug in a QueryPage: doesn't implement getQueryInfo() nor "
197 .
"getQuery() properly" );
246 return $this->
getConfig()->get(
'DisableQueryPages' );
311 $this->
getOutput()->addWikiMsg(
'specialpage-empty' );
341 $fname = static::class .
'::recache';
352 $num =
$res->numRows();
355 foreach (
$res as $i => $row ) {
356 if ( isset( $row->value ) ) {
361 $value = intval( $row->value );
369 'qc_namespace' => $row->namespace,
370 'qc_title' => $row->title,
375 $dbw->doAtomicSection(
377 function (
IDatabase $dbw, $fname ) use ( $vals ) {
378 # Clear out any old cached data
379 $dbw->
delete(
'querycache',
380 [
'qc_type' => $this->
getName() ],
383 # Save results into the querycache table on the master
384 if ( count( $vals ) ) {
385 $dbw->
insert(
'querycache', $vals, $fname );
387 # Update the querycache_info record for the page
388 $dbw->
delete(
'querycache_info',
389 [
'qci_type' => $this->
getName() ],
392 $dbw->
insert(
'querycache_info',
393 [
'qci_type' => $this->
getName(),
401 if ( !$ignoreErrors ) {
428 $dbw->delete(
'querycache', [
430 'qc_namespace' =>
$title->getNamespace(),
431 'qc_title' =>
$title->getDBkey(),
445 $fname = static::class .
'::reallyDoQuery';
451 foreach ( $order as &$field ) {
456 if ( is_array( $query ) ) {
457 $tables = isset( $query[
'tables'] ) ? (array)$query[
'tables'] : [];
458 $fields = isset( $query[
'fields'] ) ? (array)$query[
'fields'] : [];
459 $conds = isset( $query[
'conds'] ) ? (array)$query[
'conds'] : [];
460 $options = isset( $query[
'options'] ) ? (array)$query[
'options'] : [];
461 $join_conds = isset( $query[
'join_conds'] ) ? (array)$query[
'join_conds'] : [];
464 $options[
'ORDER BY'] = $order;
468 $options[
'LIMIT'] = intval(
$limit );
472 $options[
'OFFSET'] = intval(
$offset );
475 $res =
$dbr->select( $tables, $fields, $conds, $fname,
476 $options, $join_conds
481 $sql .=
' ORDER BY ' . implode(
', ', $order );
517 $options[
'LIMIT'] = intval(
$limit );
521 $options[
'OFFSET'] = intval(
$offset );
526 foreach ( $order as &$field ) {
531 $options[
'ORDER BY'] = $order;
534 return $dbr->select(
'querycache',
536 'namespace' =>
'qc_namespace',
537 'title' =>
'qc_title',
538 'value' =>
'qc_value' ],
539 [
'qc_type' => $this->
getName() ],
560 if ( $this->cachedTimestamp ===
null ) {
562 $fname = static::class .
'::getCachedTimestamp';
563 $this->cachedTimestamp =
$dbr->selectField(
'querycache_info',
'qci_timestamp',
564 [
'qci_type' => $this->
getName() ], $fname );
583 ->getLimitOffsetForUser( $this->
getUser() );
584 if ( $this->
getConfig()->
get(
'MiserMode' ) ) {
604 if ( $this->
getConfig()->
get(
'MiserMode' ) ) {
605 $limit = min( $uiLimit + 1, $maxResults - $uiOffset );
624 return max( $this->
getConfig()->
get(
'QueryCacheLimit' ), 10000 );
642 $out->addWikiMsg(
'querypage-disabled' );
648 if ( $this->limit == 0 && $this->offset == 0 ) {
651 $dbLimit = $this->
getDBLimit( $this->limit, $this->offset );
654 # select one extra row for navigation
657 # Get the cached result, select one extra row for navigation
659 if ( !$this->listoutput ) {
660 # Fetch the timestamp of this update
663 $maxResults =
$lang->formatNum( $this->
getConfig()->
get(
'QueryCacheLimit' ) );
667 $updated =
$lang->userTimeAndDate( $ts, $user );
668 $updateddate =
$lang->userDate( $ts, $user );
669 $updatedtime =
$lang->userTime( $ts, $user );
670 $out->addMeta(
'Data-Cache-Time', $ts );
671 $out->addJsConfigVars(
'dataCacheTime', $ts );
672 $out->addWikiMsg(
'perfcachedts', $updated, $updateddate, $updatedtime, $maxResults );
674 $out->addWikiMsg(
'perfcached', $maxResults );
677 # If updates on this page have been disabled, let the user know
678 # that the data set won't be refreshed for now
680 if ( isset( $disabledQueryPages[$this->
getName()] ) ) {
681 $runMode = $disabledQueryPages[$this->
getName()];
682 if ( $runMode ===
'disabled' ) {
684 "<div class=\"mw-querypage-no-updates\">\n$1\n</div>",
685 'querypage-no-updates'
690 "<div class=\"mw-querypage-updates-" . $runMode .
"\">\n$1\n</div>",
691 'querypage-updates-' . $runMode
698 $this->numRows =
$res->numRows();
703 $out->addHTML( Xml::openElement(
'div', [
'class' =>
'mw-spcontent' ] ) );
705 # Top header and navigation
706 if ( $this->shownavigation ) {
708 if ( $this->numRows > 0 ) {
709 $out->addHTML( $this->
msg(
'showingresultsinrange' )->numParams(
710 min( $this->numRows, $this->limit ), #
do not show the one extra row,
if exist
711 $this->offset + 1, ( min( $this->numRows, $this->limit ) + $this->offset ) )->parseAsBlock() );
712 # Disable the "next" link when we reach the end
713 $miserMaxResults = $this->
getConfig()->get(
'MiserMode' )
714 && ( $this->offset + $this->limit >= $this->
getMaxResults() );
715 $atEnd = ( $this->numRows <=
$this->limit ) || $miserMaxResults;
718 $out->addHTML(
'<p>' . $paging .
'</p>' );
720 # No results to show, so don't bother with "showing X of Y" etc.
721 # -- just let the user know and give up now
723 $out->addHTML( Xml::closeElement(
'div' ) );
728 # The actual results; specialist subclasses will want to handle this
729 # with more than a straight list, so we hand them the info, plus
730 # an OutputPage, and let them get on with it
735 min( $this->numRows, $this->limit ), #
do not format the one extra row,
if exist
738 # Repeat the paging links at the bottom
739 if ( $this->shownavigation ) {
740 $out->addHTML(
'<p>' . $paging .
'</p>' );
743 $out->addHTML( Xml::closeElement(
'div' ) );
762 if ( !$this->listoutput ) {
766 # $res might contain the whole 1,000 rows, so we read up to
767 # $num [should update this to use a Pager]
768 for ( $i = 0; $i < $num && $row =
$res->fetchObject(); $i++ ) {
771 $html[] = $this->listoutput
773 :
"<li>{$line}</li>\n";
777 if ( !$this->listoutput ) {
781 $html = $this->listoutput
782 ? MediaWikiServices::getInstance()->getContentLanguage()->listToText( $html )
783 : implode(
'', $html );
785 $out->addHTML( $html );
794 return "\n<ol start='" . (
$offset + 1 ) .
"' class='special'>\n";
824 if ( !
$res->numRows() ) {
829 foreach (
$res as $row ) {
830 $batch->
add( $ns ?? $row->namespace, $row->title );
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Class representing a list of titles The execute() method checks them all for existence and adds them ...
This is a class for doing query pages; since they're almost all the same, we factor out some of the f...
isExpensive()
Is this query expensive (for some definition of expensive)? Then we don't let it run in miser mode.
linkParameters()
If using extra form wheely-dealies, return a set of parameters here as an associative array.
getMaxResults()
Get max number of results we can return in miser mode.
doQuery( $offset=false, $limit=false)
Somewhat deprecated, you probably want to be using execute()
executeLBFromResultWrapper(IResultWrapper $res, $ns=null)
Creates a new LinkBatch object, adds all pages from the passed result wrapper (MUST include title and...
setListoutput( $bool)
A mutator for $this->listoutput;.
static getDisabledQueryPages(Config $config)
Get a list of query pages disabled and with it's run mode.
recache( $limit, $ignoreErrors=true)
Clear the cache and save new results.
fetchFromCache( $limit, $offset=false)
Fetch the query results from the query cache Stable to override.
int $offset
The offset and limit in use, as passed to the query() function.
outputResults( $out, $skin, $dbr, $res, $num, $offset)
Format and output report results using the given information plus OutputPage.
isCached()
Whether or not the output of the page in question is retrieved from the database cache.
sortDescending()
Override to sort by increasing values.
formatResult( $skin, $result)
Formats the results of the query for display.
isSyndicated()
Sometime we don't want to build rss / atom feeds.
string null $cachedTimestamp
static getPages()
Get a list of query page classes and their associated special pages, for periodic updates.
bool $shownavigation
Whether to show prev/next links.
reallyDoQuery( $limit, $offset=false)
Run the query and return the result Stable to override.
isCacheable()
Is the output of this query cacheable? Non-cacheable expensive pages will be disabled in miser mode a...
getOrderFields()
Subclasses return an array of fields to order by here.
showEmptyText()
Outputs some kind of an informative message (via OutputPage) to let the user know that the query retu...
usesTimestamps()
Does this query return timestamps rather than integers in its 'value' field? If true,...
getCacheOrderFields()
Return the order fields for fetchFromCache.
getQueryInfo()
Subclasses return an SQL query here, formatted as an array with the following keys: tables => Table(s...
getDBLimit( $uiLimit, $uiOffset)
What is limit to fetch from DB.
int $numRows
The number of rows returned by the query.
preprocessResults( $db, $res)
Do any necessary preprocessing of the result object.
getSQL()
For back-compat, subclasses may return a raw SQL query here, as a string.
getPageHeader()
The content returned by this function will be output before any result.
bool $listoutput
Whether or not we want plain listoutput rather than an ordered list.
execute( $par)
This is the actual workhorse.
getLimitOffset()
Returns limit and offset, as returned by $this->getRequest()->getLimitOffsetForUser().
getRecacheDB()
Get a DB connection to be used for slow recache queries Stable to override.
Parent class for all special pages.
outputHeader( $summaryMessageKey='')
Outputs a summary message on top of special pages Per default the message key is the canonical name o...
getName()
Get the name of this Special Page.
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!...
getOutput()
Get the OutputPage being used for this instance.
getUser()
Shortcut to get the User executing this instance.
buildPrevNextNavigation( $offset, $limit, array $query=[], $atend=false, $subpage=false)
Generate (prev x| next x) (20|50|100...) type links for paging.
getSkin()
Shortcut to get the skin being used for this instance.
checkPermissions()
Checks if userCanExecute, and if not throws a PermissionsError.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getConfig()
Shortcut to get main config object.
getRequest()
Get the WebRequest being used for this instance.
getLanguage()
Shortcut to get user's language.
Interface for configuration instances.
get( $name)
Get a configuration variable such as "Sitename" or "UploadMaintenance.".
if(!isset( $args[0])) $lang