wiki.techinc.nl/includes/specials/SpecialPagesWithProp.php
Timo Tijhof 15eac4c279 mediawiki.special: Combine various tiny specialpage style modules
These stylesheets are sufficiently tiny that it doesn't make sense to
offer them the ability to be loaded separately from each other (saving
bytes in double-digits) at the cost of 1) exporting a dedicated registry
item with meta data shipped on every page view, 2) reduced cache re-use
from increased fragmentation.

Instead, move these to the 'mediawiki.special' style module.
The entries retain their own files to keep them as easy to find
and edit as before.

Where not already, ensure addModuleStyles() is always placed above
any addModules() call in the same method. The load order isn't
affected by the call order, but given blocking style-modules load
before async JS, it helps to order them in a way that visually
matches the effective load order (from top to bottom).

The following 7 modules were remove without deprecation:

1. "mediawiki.special.apisandbox.styles" (1 rule)
2. "mediawiki.special.edittags.styles" (3 rules)
3. "mediawiki.special.movePage.styles" (1 rule)
4. "mediawiki.special.pagesWithProp" (1 rule)
5. "mediawiki.special.upload.styles" (2 rules)
6. "mediawiki.special.watchlist.styles" (3 rules)
7. "mediawiki.special.comparepages.styles" (4 rules)

These module names were only used on the core classes loading them, and
aren't depended on outside core by module name, rather, extensions and
gadgets depend on the styles styles being loaded in a blocking manner on
these pages, which remains unaffected.

Bug: T192623
Change-Id: I6e663dc3c80c7104c9b9abdde44c654543185373
2018-05-16 22:47:15 +00:00

240 lines
5.9 KiB
PHP

<?php
/**
* Implements Special:PagesWithProp
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
* @since 1.21
* @file
* @ingroup SpecialPage
*/
/**
* Special:PagesWithProp to search the page_props table
* @ingroup SpecialPage
* @since 1.21
*/
class SpecialPagesWithProp extends QueryPage {
/**
* @var string|null
*/
private $propName = null;
/**
* @var string[]|null
*/
private $existingPropNames = null;
/**
* @var bool
*/
private $reverse = false;
/**
* @var bool
*/
private $sortByValue = false;
function __construct( $name = 'PagesWithProp' ) {
parent::__construct( $name );
}
function isCacheable() {
return false;
}
public function execute( $par ) {
$this->setHeaders();
$this->outputHeader();
$this->getOutput()->addModuleStyles( 'mediawiki.special' );
$request = $this->getRequest();
$propname = $request->getVal( 'propname', $par );
$this->reverse = $request->getBool( 'reverse' );
$this->sortByValue = $request->getBool( 'sortbyvalue' );
$propnames = $this->getExistingPropNames();
$form = HTMLForm::factory( 'ooui', [
'propname' => [
'type' => 'combobox',
'name' => 'propname',
'options' => $propnames,
'default' => $propname,
'label-message' => 'pageswithprop-prop',
'required' => true,
],
'reverse' => [
'type' => 'check',
'name' => 'reverse',
'default' => $this->reverse,
'label-message' => 'pageswithprop-reverse',
'required' => false,
],
'sortbyvalue' => [
'type' => 'check',
'name' => 'sortbyvalue',
'default' => $this->sortByValue,
'label-message' => 'pageswithprop-sortbyvalue',
'required' => false,
]
], $this->getContext() );
$form->setMethod( 'get' );
$form->setSubmitCallback( [ $this, 'onSubmit' ] );
$form->setWrapperLegendMsg( 'pageswithprop-legend' );
$form->addHeaderText( $this->msg( 'pageswithprop-text' )->parseAsBlock() );
$form->setSubmitTextMsg( 'pageswithprop-submit' );
$form->prepareForm();
$form->displayForm( false );
if ( $propname !== '' && $propname !== null ) {
$form->trySubmit();
}
}
public function onSubmit( $data, $form ) {
$this->propName = $data['propname'];
parent::execute( $data['propname'] );
}
/**
* Return an array of subpages beginning with $search that this special page will accept.
*
* @param string $search Prefix to search for
* @param int $limit Maximum number of results to return
* @param int $offset Number of pages to skip
* @return string[] Matching subpages
*/
public function prefixSearchSubpages( $search, $limit, $offset ) {
$subpages = array_keys( $this->queryExistingProps( $limit, $offset ) );
// We've already limited and offsetted, set to N and 0 respectively.
return self::prefixSearchArray( $search, count( $subpages ), $subpages, 0 );
}
/**
* Disable RSS/Atom feeds
* @return bool
*/
function isSyndicated() {
return false;
}
public function getQueryInfo() {
return [
'tables' => [ 'page_props', 'page' ],
'fields' => [
'page_id' => 'pp_page',
'page_namespace',
'page_title',
'page_len',
'page_is_redirect',
'page_latest',
'pp_value',
],
'conds' => [
'pp_propname' => $this->propName,
],
'join_conds' => [
'page' => [ 'INNER JOIN', 'page_id = pp_page' ]
],
'options' => []
];
}
function getOrderFields() {
$sort = [ 'page_id' ];
if ( $this->sortByValue ) {
array_unshift( $sort, 'pp_sortkey' );
}
return $sort;
}
/**
* @return bool
*/
public function sortDescending() {
return !$this->reverse;
}
/**
* @param Skin $skin
* @param object $result Result row
* @return string
*/
function formatResult( $skin, $result ) {
$title = Title::newFromRow( $result );
$ret = $this->getLinkRenderer()->makeKnownLink( $title );
if ( $result->pp_value !== '' ) {
// Do not show very long or binary values on the special page
$valueLength = strlen( $result->pp_value );
$isBinary = strpos( $result->pp_value, "\0" ) !== false;
$isTooLong = $valueLength > 1024;
if ( $isBinary || $isTooLong ) {
$message = $this
->msg( $isBinary ? 'pageswithprop-prophidden-binary' : 'pageswithprop-prophidden-long' )
->params( $this->getLanguage()->formatSize( $valueLength ) );
$propValue = Html::element( 'span', [ 'class' => 'prop-value-hidden' ], $message->text() );
} else {
$propValue = Html::element( 'span', [ 'class' => 'prop-value' ], $result->pp_value );
}
$ret .= $this->msg( 'colon-separator' )->escaped() . $propValue;
}
return $ret;
}
public function getExistingPropNames() {
if ( $this->existingPropNames === null ) {
$this->existingPropNames = $this->queryExistingProps();
}
return $this->existingPropNames;
}
protected function queryExistingProps( $limit = null, $offset = 0 ) {
$opts = [
'DISTINCT', 'ORDER BY' => 'pp_propname'
];
if ( $limit ) {
$opts['LIMIT'] = $limit;
}
if ( $offset ) {
$opts['OFFSET'] = $offset;
}
$res = wfGetDB( DB_REPLICA )->select(
'page_props',
'pp_propname',
'',
__METHOD__,
$opts
);
$propnames = [];
foreach ( $res as $row ) {
$propnames[$row->pp_propname] = $row->pp_propname;
}
return $propnames;
}
protected function getGroupName() {
return 'pages';
}
}