80 [ SpecialAncientPages::class,
'Ancientpages' ],
81 [ SpecialBrokenRedirects::class,
'BrokenRedirects' ],
82 [ SpecialDeadendPages::class,
'Deadendpages' ],
83 [ SpecialDoubleRedirects::class,
'DoubleRedirects' ],
84 [ SpecialFileDuplicateSearch::class,
'FileDuplicateSearch' ],
85 [ SpecialListDuplicatedFiles::class,
'ListDuplicatedFiles' ],
86 [ SpecialLinkSearch::class,
'LinkSearch' ],
87 [ SpecialListRedirects::class,
'Listredirects' ],
88 [ SpecialLonelyPages::class,
'Lonelypages' ],
89 [ SpecialLongPages::class,
'Longpages' ],
90 [ SpecialMediaStatistics::class,
'MediaStatistics' ],
91 [ SpecialMIMESearch::class,
'MIMEsearch' ],
92 [ SpecialMostCategories::class,
'Mostcategories' ],
93 [ MostimagesPage::class,
'Mostimages' ],
94 [ SpecialMostInterwikis::class,
'Mostinterwikis' ],
95 [ SpecialMostLinkedCategories::class,
'Mostlinkedcategories' ],
96 [ SpecialMostLinkedTemplates::class,
'Mostlinkedtemplates' ],
97 [ SpecialMostLinked::class,
'Mostlinked' ],
98 [ SpecialMostRevisions::class,
'Mostrevisions' ],
99 [ SpecialFewestRevisions::class,
'Fewestrevisions' ],
100 [ SpecialShortPages::class,
'Shortpages' ],
101 [ SpecialUncategorizedCategories::class,
'Uncategorizedcategories' ],
102 [ SpecialUncategorizedPages::class,
'Uncategorizedpages' ],
103 [ SpecialUncategorizedImages::class,
'Uncategorizedimages' ],
104 [ SpecialUncategorizedTemplates::class,
'Uncategorizedtemplates' ],
105 [ SpecialUnusedCategories::class,
'Unusedcategories' ],
106 [ SpecialUnusedImages::class,
'Unusedimages' ],
107 [ SpecialWantedCategories::class,
'Wantedcategories' ],
108 [ WantedFilesPage::class,
'Wantedfiles' ],
109 [ WantedPagesPage::class,
'Wantedpages' ],
110 [ SpecialWantedTemplates::class,
'Wantedtemplates' ],
111 [ SpecialUnwatchedPages::class,
'Unwatchedpages' ],
112 [ SpecialUnusedTemplates::class,
'Unusedtemplates' ],
113 [ SpecialWithoutInterwiki::class,
'Withoutinterwiki' ],
115 Hooks::run(
'wgQueryPages', [ &$qp ] );
127 $disableQueryPageUpdate = $config->
get(
'DisableQueryPageUpdate' );
129 if ( !is_array( $disableQueryPageUpdate ) ) {
134 foreach ( $disableQueryPageUpdate as $name =>
$runMode ) {
135 if ( is_int( $name ) ) {
151 $this->listoutput = $bool;
192 throw new MWException(
"Bug in a QueryPage: doesn't implement getQueryInfo() nor "
193 .
"getQuery() properly" );
238 return $this->
getConfig()->get(
'DisableQueryPages' );
299 $this->
getOutput()->addWikiMsg(
'specialpage-empty' );
326 $fname = static::class .
'::recache';
337 $num =
$res->numRows();
340 foreach (
$res as $i => $row ) {
341 if ( isset( $row->value ) ) {
346 $value = intval( $row->value );
354 'qc_namespace' => $row->namespace,
355 'qc_title' => $row->title,
360 $dbw->doAtomicSection(
362 function (
IDatabase $dbw, $fname ) use ( $vals ) {
363 # Clear out any old cached data
364 $dbw->
delete(
'querycache',
365 [
'qc_type' => $this->
getName() ],
368 # Save results into the querycache table on the master
369 if ( count( $vals ) ) {
370 $dbw->
insert(
'querycache', $vals, $fname );
372 # Update the querycache_info record for the page
373 $dbw->
delete(
'querycache_info',
374 [
'qci_type' => $this->
getName() ],
377 $dbw->
insert(
'querycache_info',
378 [
'qci_type' => $this->
getName(),
386 if ( !$ignoreErrors ) {
412 $dbw->delete(
'querycache', [
414 'qc_namespace' =>
$title->getNamespace(),
415 'qc_title' =>
$title->getDBkey(),
428 $fname = static::class .
'::reallyDoQuery';
434 foreach ( $order as &$field ) {
439 if ( is_array( $query ) ) {
440 $tables = isset( $query[
'tables'] ) ? (array)$query[
'tables'] : [];
441 $fields = isset( $query[
'fields'] ) ? (array)$query[
'fields'] : [];
442 $conds = isset( $query[
'conds'] ) ? (array)$query[
'conds'] : [];
443 $options = isset( $query[
'options'] ) ? (array)$query[
'options'] : [];
444 $join_conds = isset( $query[
'join_conds'] ) ? (array)$query[
'join_conds'] : [];
447 $options[
'ORDER BY'] = $order;
451 $options[
'LIMIT'] = intval(
$limit );
455 $options[
'OFFSET'] = intval(
$offset );
458 $res =
$dbr->select( $tables, $fields, $conds, $fname,
459 $options, $join_conds
464 $sql .=
' ORDER BY ' . implode(
', ', $order );
498 $options[
'LIMIT'] = intval(
$limit );
502 $options[
'OFFSET'] = intval(
$offset );
507 foreach ( $order as &$field ) {
512 $options[
'ORDER BY'] = $order;
515 return $dbr->select(
'querycache',
517 'namespace' =>
'qc_namespace',
518 'title' =>
'qc_title',
519 'value' =>
'qc_value' ],
520 [
'qc_type' => $this->
getName() ],
540 if ( is_null( $this->cachedTimestamp ) ) {
542 $fname = static::class .
'::getCachedTimestamp';
543 $this->cachedTimestamp =
$dbr->selectField(
'querycache_info',
'qci_timestamp',
544 [
'qci_type' => $this->
getName() ], $fname );
563 if ( $this->
getConfig()->
get(
'MiserMode' ) ) {
583 if ( $this->
getConfig()->
get(
'MiserMode' ) ) {
584 $limit = min( $uiLimit + 1, $maxResults - $uiOffset );
602 return max( $this->
getConfig()->
get(
'QueryCacheLimit' ), 10000 );
623 $out->addWikiMsg(
'querypage-disabled' );
629 if ( $this->limit == 0 && $this->offset == 0 ) {
632 $dbLimit = $this->
getDBLimit( $this->limit, $this->offset );
635 # select one extra row for navigation
638 # Get the cached result, select one extra row for navigation
640 if ( !$this->listoutput ) {
641 # Fetch the timestamp of this update
644 $maxResults =
$lang->formatNum( $this->
getConfig()->
get(
'QueryCacheLimit' ) );
647 $updated =
$lang->userTimeAndDate( $ts, $user );
648 $updateddate =
$lang->userDate( $ts, $user );
649 $updatedtime =
$lang->userTime( $ts, $user );
650 $out->addMeta(
'Data-Cache-Time', $ts );
651 $out->addJsConfigVars(
'dataCacheTime', $ts );
652 $out->addWikiMsg(
'perfcachedts', $updated, $updateddate, $updatedtime, $maxResults );
654 $out->addWikiMsg(
'perfcached', $maxResults );
657 # If updates on this page have been disabled, let the user know
658 # that the data set won't be refreshed for now
660 if ( isset( $disabledQueryPages[$this->
getName()] ) ) {
664 "<div class=\"mw-querypage-no-updates\">\n$1\n</div>",
665 'querypage-no-updates'
670 "<div class=\"mw-querypage-updates-" .
$runMode .
"\">\n$1\n</div>",
678 $this->numRows =
$res->numRows();
683 $out->addHTML( Xml::openElement(
'div', [
'class' =>
'mw-spcontent' ] ) );
685 # Top header and navigation
686 if ( $this->shownavigation ) {
688 if ( $this->numRows > 0 ) {
689 $out->addHTML( $this->
msg(
'showingresultsinrange' )->numParams(
690 min( $this->numRows, $this->limit ), #
do not show the one extra row,
if exist
691 $this->offset + 1, ( min( $this->numRows, $this->limit ) + $this->offset ) )->parseAsBlock() );
692 # Disable the "next" link when we reach the end
693 $miserMaxResults = $this->
getConfig()->get(
'MiserMode' )
694 && ( $this->offset + $this->limit >= $this->
getMaxResults() );
695 $atEnd = ( $this->numRows <=
$this->limit ) || $miserMaxResults;
698 $out->addHTML(
'<p>' . $paging .
'</p>' );
700 # No results to show, so don't bother with "showing X of Y" etc.
701 # -- just let the user know and give up now
703 $out->addHTML( Xml::closeElement(
'div' ) );
708 # The actual results; specialist subclasses will want to handle this
709 # with more than a straight list, so we hand them the info, plus
710 # an OutputPage, and let them get on with it
715 min( $this->numRows, $this->limit ), #
do not format the one extra row,
if exist
718 # Repeat the paging links at the bottom
719 if ( $this->shownavigation ) {
720 $out->addHTML(
'<p>' . $paging .
'</p>' );
723 $out->addHTML( Xml::closeElement(
'div' ) );
740 if ( !$this->listoutput ) {
744 # $res might contain the whole 1,000 rows, so we read up to
745 # $num [should update this to use a Pager]
746 for ( $i = 0; $i < $num && $row =
$res->fetchObject(); $i++ ) {
749 $html[] = $this->listoutput
751 :
"<li>{$line}</li>\n";
755 if ( !$this->listoutput ) {
759 $html = $this->listoutput
760 ? MediaWikiServices::getInstance()->getContentLanguage()->listToText( $html )
761 : implode(
'', $html );
763 $out->addHTML( $html );
772 return "\n<ol start='" . (
$offset + 1 ) .
"' class='special'>\n";
801 if ( !
$res->numRows() ) {
806 foreach (
$res as $row ) {
807 $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.
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.
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()->getLimitOffset().
getRecacheDB()
Get a DB connection to be used for slow recache queries.
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.
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.
displayRestrictionError()
Output an error message telling the user what access level they have to have.
getLanguage()
Shortcut to get user's language.
userCanExecute(User $user)
Checks if the given user (identified by an object) can execute this special page (as defined by $mRes...
Interface for configuration instances.
get( $name)
Get a configuration variable such as "Sitename" or "UploadMaintenance.".
if(!isset( $args[0])) $lang