MediaWiki  master
SpecialPagesWithProp.php
Go to the documentation of this file.
1 <?php
26 
33 
37  private $propName = null;
38 
42  private $existingPropNames = null;
43 
47  private $ns;
48 
52  private $reverse = false;
53 
57  private $sortByValue = false;
58 
63  parent::__construct( 'PagesWithProp' );
64  $this->setDBLoadBalancer( $loadBalancer );
65  }
66 
67  public function isCacheable() {
68  return false;
69  }
70 
71  public function execute( $par ) {
72  $this->setHeaders();
73  $this->outputHeader();
74  $this->getOutput()->addModuleStyles( 'mediawiki.special' );
75 
76  $request = $this->getRequest();
77  $propname = $request->getVal( 'propname', $par );
78  $this->ns = $request->getIntOrNull( 'namespace' );
79  $this->reverse = $request->getBool( 'reverse' );
80  $this->sortByValue = $request->getBool( 'sortbyvalue' );
81 
82  $propnames = $this->getExistingPropNames();
83 
84  $fields = [
85  'propname' => [
86  'type' => 'combobox',
87  'name' => 'propname',
88  'options' => $propnames,
89  'default' => $propname,
90  'label-message' => 'pageswithprop-prop',
91  'required' => true,
92  ],
93  'namespace' => [
94  'type' => 'namespaceselect',
95  'name' => 'namespace',
96  'label-message' => 'namespace',
97  'all' => '',
98  'default' => $this->ns,
99  ],
100  'reverse' => [
101  'type' => 'check',
102  'name' => 'reverse',
103  'default' => $this->reverse,
104  'label-message' => 'pageswithprop-reverse',
105  'required' => false,
106  ],
107  'sortbyvalue' => [
108  'type' => 'check',
109  'name' => 'sortbyvalue',
110  'default' => $this->sortByValue,
111  'label-message' => 'pageswithprop-sortbyvalue',
112  'required' => false,
113  ]
114  ];
115 
116  $form = HTMLForm::factory( 'ooui', $fields, $this->getContext() )
117  ->setMethod( 'get' )
118  ->setTitle( $this->getPageTitle() ) // Remove subpage
119  ->setSubmitCallback( [ $this, 'onSubmit' ] )
120  ->setWrapperLegendMsg( 'pageswithprop-legend' )
121  ->addHeaderText( $this->msg( 'pageswithprop-text' )->parseAsBlock() )
122  ->setSubmitTextMsg( 'pageswithprop-submit' )
123  ->prepareForm();
124  $form->displayForm( false );
125  if ( $propname !== '' && $propname !== null ) {
126  $form->trySubmit();
127  }
128  }
129 
130  public function onSubmit( $data, $form ) {
131  $this->propName = $data['propname'];
132  parent::execute( $data['propname'] );
133  }
134 
143  public function prefixSearchSubpages( $search, $limit, $offset ) {
144  $subpages = array_keys( $this->queryExistingProps( $limit, $offset ) );
145  // We've already limited and offsetted, set to N and 0 respectively.
146  return self::prefixSearchArray( $search, count( $subpages ), $subpages, 0 );
147  }
148 
153  public function isSyndicated() {
154  return false;
155  }
156 
160  protected function linkParameters() {
161  $params = [
162  'reverse' => $this->reverse,
163  'sortbyvalue' => $this->sortByValue,
164  ];
165  if ( $this->ns !== null ) {
166  $params['namespace'] = $this->ns;
167  }
168  return $params;
169  }
170 
171  public function getQueryInfo() {
172  $query = [
173  'tables' => [ 'page_props', 'page' ],
174  'fields' => [
175  'page_id' => 'pp_page',
176  'page_namespace',
177  'page_title',
178  'page_len',
179  'page_is_redirect',
180  'page_latest',
181  'pp_value',
182  ],
183  'conds' => [
184  'pp_propname' => $this->propName,
185  ],
186  'join_conds' => [
187  'page' => [ 'JOIN', 'page_id = pp_page' ]
188  ],
189  'options' => []
190  ];
191 
192  if ( $this->ns !== null ) {
193  $query['conds']['page_namespace'] = $this->ns;
194  }
195 
196  return $query;
197  }
198 
199  protected function getOrderFields() {
200  $sort = [ 'page_id' ];
201  if ( $this->sortByValue ) {
202  array_unshift( $sort, 'pp_sortkey' );
203  }
204  return $sort;
205  }
206 
210  public function sortDescending() {
211  return !$this->reverse;
212  }
213 
219  public function formatResult( $skin, $result ) {
220  $title = Title::newFromRow( $result );
221  $ret = $this->getLinkRenderer()->makeKnownLink( $title );
222  if ( $result->pp_value !== '' ) {
223  // Do not show very long or binary values on the special page
224  $valueLength = strlen( $result->pp_value );
225  $isBinary = strpos( $result->pp_value, "\0" ) !== false;
226  $isTooLong = $valueLength > 1024;
227 
228  if ( $isBinary || $isTooLong ) {
229  $message = $this
230  ->msg( $isBinary ? 'pageswithprop-prophidden-binary' : 'pageswithprop-prophidden-long' )
231  ->sizeParams( $valueLength );
232 
233  $propValue = Html::element( 'span', [ 'class' => 'prop-value-hidden' ], $message->text() );
234  } else {
235  $propValue = Html::element( 'span', [ 'class' => 'prop-value' ], $result->pp_value );
236  }
237 
238  $ret .= $this->msg( 'colon-separator' )->escaped() . $propValue;
239  }
240 
241  return $ret;
242  }
243 
244  public function getExistingPropNames() {
245  if ( $this->existingPropNames === null ) {
246  $this->existingPropNames = $this->queryExistingProps();
247  }
249  }
250 
251  protected function queryExistingProps( $limit = null, $offset = 0 ) {
252  $opts = [
253  'DISTINCT', 'ORDER BY' => 'pp_propname'
254  ];
255  if ( $limit ) {
256  $opts['LIMIT'] = $limit;
257  }
258  if ( $offset ) {
259  $opts['OFFSET'] = $offset;
260  }
261 
262  $dbr = $this->getDBLoadBalancer()->getConnectionRef( ILoadBalancer::DB_REPLICA );
263  $res = $dbr->select(
264  'page_props',
265  'pp_propname',
266  '',
267  __METHOD__,
268  $opts
269  );
270 
271  $propnames = [];
272  foreach ( $res as $row ) {
273  $propnames[$row->pp_propname] = $row->pp_propname;
274  }
275 
276  return $propnames;
277  }
278 
279  protected function getGroupName() {
280  return 'pages';
281  }
282 }
static factory( $displayFormat, $descriptor, IContextSource $context, $messagePrefix='')
Construct a HTMLForm object for given display type.
Definition: HTMLForm.php:338
static element( $element, $attribs=[], $contents='')
Identical to rawElement(), but HTML-escapes $contents (like Xml::element()).
Definition: Html.php:236
This is a class for doing query pages; since they're almost all the same, we factor out some of the f...
Definition: QueryPage.php:42
setDBLoadBalancer(ILoadBalancer $loadBalancer)
Definition: QueryPage.php:895
int $offset
The offset and limit in use, as passed to the query() function.
Definition: QueryPage.php:47
int $limit
Definition: QueryPage.php:50
getDBLoadBalancer()
Definition: QueryPage.php:903
ILoadBalancer null $loadBalancer
Definition: QueryPage.php:72
outputHeader( $summaryMessageKey='')
Outputs a summary message on top of special pages Per default the message key is the canonical name o...
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
getOutput()
Get the OutputPage being used for this instance.
static prefixSearchArray( $search, $limit, array $subpages, $offset)
Helper function for implementations of prefixSearchSubpages() that filter the values in memory (as op...
getContext()
Gets the context this SpecialPage is executed in.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getRequest()
Get the WebRequest being used for this instance.
getPageTitle( $subpage=false)
Get a self-referential title object.
Special:PagesWithProp to search the page_props table.
execute( $par)
This is the actual workhorse.
linkParameters()
If using extra form wheely-dealies, return a set of parameters here as an associative array....
queryExistingProps( $limit=null, $offset=0)
getQueryInfo()
Subclasses return an SQL query here, formatted as an array with the following keys: tables => Table(s...
isSyndicated()
Disable RSS/Atom feeds.
isCacheable()
Is the output of this query cacheable? Non-cacheable expensive pages will be disabled in miser mode a...
string[] null $existingPropNames
getOrderFields()
Subclasses return an array of fields to order by here.
__construct(ILoadBalancer $loadBalancer)
prefixSearchSubpages( $search, $limit, $offset)
Return an array of subpages beginning with $search that this special page will accept.
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
formatResult( $skin, $result)
static newFromRow( $row)
Make a Title object from a DB row.
Definition: Title.php:573
Database cluster connection, tracking, load balancing, and transaction manager interface.
const DB_REPLICA
Definition: defines.php:25