MediaWiki  master
SpecialNewpages.php
Go to the documentation of this file.
1 <?php
25 
35  protected $opts;
37  protected $customFilters;
38 
39  protected $showNavigation = false;
40 
41  public function __construct() {
42  parent::__construct( 'Newpages' );
43  }
44 
48  protected function setup( $par ) {
49  $opts = new FormOptions();
50  $this->opts = $opts; // bind
51  $opts->add( 'hideliu', false );
52  $opts->add( 'hidepatrolled', $this->getUser()->getBoolOption( 'newpageshidepatrolled' ) );
53  $opts->add( 'hidebots', false );
54  $opts->add( 'hideredirs', true );
55  $opts->add( 'limit', $this->getUser()->getIntOption( 'rclimit' ) );
56  $opts->add( 'offset', '' );
57  $opts->add( 'namespace', '0' );
58  $opts->add( 'username', '' );
59  $opts->add( 'feed', '' );
60  $opts->add( 'tagfilter', '' );
61  $opts->add( 'invert', false );
62  $opts->add( 'associated', false );
63  $opts->add( 'size-mode', 'max' );
64  $opts->add( 'size', 0 );
65 
66  $this->customFilters = [];
67  Hooks::run( 'SpecialNewPagesFilters', [ $this, &$this->customFilters ] );
68  // @phan-suppress-next-line PhanEmptyForeach False positive
69  foreach ( $this->customFilters as $key => $params ) {
70  $opts->add( $key, $params['default'] );
71  }
72 
74  if ( $par ) {
75  $this->parseParams( $par );
76  }
77 
78  $opts->validateIntBounds( 'limit', 0, 5000 );
79  }
80 
84  protected function parseParams( $par ) {
85  $bits = preg_split( '/\s*,\s*/', trim( $par ) );
86  foreach ( $bits as $bit ) {
87  if ( $bit === 'shownav' ) {
88  $this->showNavigation = true;
89  }
90  if ( $bit === 'hideliu' ) {
91  $this->opts->setValue( 'hideliu', true );
92  }
93  if ( $bit === 'hidepatrolled' ) {
94  $this->opts->setValue( 'hidepatrolled', true );
95  }
96  if ( $bit === 'hidebots' ) {
97  $this->opts->setValue( 'hidebots', true );
98  }
99  if ( $bit === 'showredirs' ) {
100  $this->opts->setValue( 'hideredirs', false );
101  }
102  if ( is_numeric( $bit ) ) {
103  $this->opts->setValue( 'limit', intval( $bit ) );
104  }
105 
106  $m = [];
107  if ( preg_match( '/^limit=(\d+)$/', $bit, $m ) ) {
108  $this->opts->setValue( 'limit', intval( $m[1] ) );
109  }
110  // PG offsets not just digits!
111  if ( preg_match( '/^offset=([^=]+)$/', $bit, $m ) ) {
112  $this->opts->setValue( 'offset', intval( $m[1] ) );
113  }
114  if ( preg_match( '/^username=(.*)$/', $bit, $m ) ) {
115  $this->opts->setValue( 'username', $m[1] );
116  }
117  if ( preg_match( '/^namespace=(.*)$/', $bit, $m ) ) {
118  $ns = $this->getLanguage()->getNsIndex( $m[1] );
119  if ( $ns !== false ) {
120  $this->opts->setValue( 'namespace', $ns );
121  }
122  }
123  }
124  }
125 
131  public function execute( $par ) {
132  $out = $this->getOutput();
133 
134  $this->setHeaders();
135  $this->outputHeader();
136 
137  $this->showNavigation = !$this->including(); // Maybe changed in setup
138  $this->setup( $par );
139 
140  $this->addHelpLink( 'Help:New pages' );
141 
142  if ( !$this->including() ) {
143  // Settings
144  $this->form();
145 
146  $feedType = $this->opts->getValue( 'feed' );
147  if ( $feedType ) {
148  $this->feed( $feedType );
149 
150  return;
151  }
152 
153  $allValues = $this->opts->getAllValues();
154  unset( $allValues['feed'] );
155  $out->setFeedAppendQuery( wfArrayToCgi( $allValues ) );
156  }
157 
158  $pager = new NewPagesPager( $this, $this->opts );
159  $pager->mLimit = $this->opts->getValue( 'limit' );
160  $pager->mOffset = $this->opts->getValue( 'offset' );
161 
162  if ( $pager->getNumRows() ) {
163  $navigation = '';
164  if ( $this->showNavigation ) {
165  $navigation = $pager->getNavigationBar();
166  }
167  $out->addHTML( $navigation . $pager->getBody() . $navigation );
168  // Add styles for change tags
169  $out->addModuleStyles( 'mediawiki.interface.helpers.styles' );
170  } else {
171  $out->addWikiMsg( 'specialpage-empty' );
172  }
173  }
174 
175  protected function filterLinks() {
176  // show/hide links
177  $showhide = [ $this->msg( 'show' )->escaped(), $this->msg( 'hide' )->escaped() ];
178 
179  // Option value -> message mapping
180  $filters = [
181  'hideliu' => 'rcshowhideliu',
182  'hidepatrolled' => 'rcshowhidepatr',
183  'hidebots' => 'rcshowhidebots',
184  'hideredirs' => 'whatlinkshere-hideredirs'
185  ];
186  foreach ( $this->customFilters as $key => $params ) {
187  $filters[$key] = $params['msg'];
188  }
189 
190  // Disable some if needed
191  if ( !$this->canAnonymousUsersCreatePages() ) {
192  unset( $filters['hideliu'] );
193  }
194  if ( !$this->getUser()->useNPPatrol() ) {
195  unset( $filters['hidepatrolled'] );
196  }
197 
198  $links = [];
199  $changed = $this->opts->getChangedValues();
200  unset( $changed['offset'] ); // Reset offset if query type changes
201 
202  // wfArrayToCgi(), called from LinkRenderer/Title, will not output null and false values
203  // to the URL, which would omit some options (T158504). Fix it by explicitly setting them
204  // to 0 or 1.
205  // Also do this only for boolean options, not eg. namespace or tagfilter
206  foreach ( $changed as $key => $value ) {
207  if ( array_key_exists( $key, $filters ) ) {
208  $changed[$key] = $changed[$key] ? '1' : '0';
209  }
210  }
211 
212  $self = $this->getPageTitle();
213  $linkRenderer = $this->getLinkRenderer();
214  foreach ( $filters as $key => $msg ) {
215  $onoff = 1 - $this->opts->getValue( $key );
216  $link = $linkRenderer->makeLink(
217  $self,
218  new HtmlArmor( $showhide[$onoff] ),
219  [],
220  [ $key => $onoff ] + $changed
221  );
222  $links[$key] = $this->msg( $msg )->rawParams( $link )->escaped();
223  }
224 
225  return $this->getLanguage()->pipeList( $links );
226  }
227 
228  protected function form() {
229  $out = $this->getOutput();
230 
231  // Consume values
232  $this->opts->consumeValue( 'offset' ); // don't carry offset, DWIW
233  $namespace = $this->opts->consumeValue( 'namespace' );
234  $username = $this->opts->consumeValue( 'username' );
235  $tagFilterVal = $this->opts->consumeValue( 'tagfilter' );
236  $nsinvert = $this->opts->consumeValue( 'invert' );
237  $nsassociated = $this->opts->consumeValue( 'associated' );
238 
239  $size = $this->opts->consumeValue( 'size' );
240  $max = $this->opts->consumeValue( 'size-mode' ) === 'max';
241 
242  // Check username input validity
243  $ut = Title::makeTitleSafe( NS_USER, $username );
244  $userText = $ut ? $ut->getText() : '';
245 
246  $formDescriptor = [
247  'namespace' => [
248  'type' => 'namespaceselect',
249  'name' => 'namespace',
250  'label-message' => 'namespace',
251  'default' => $namespace,
252  ],
253  'nsinvert' => [
254  'type' => 'check',
255  'name' => 'invert',
256  'label-message' => 'invert',
257  'default' => $nsinvert,
258  'tooltip' => 'invert',
259  ],
260  'nsassociated' => [
261  'type' => 'check',
262  'name' => 'associated',
263  'label-message' => 'namespace_association',
264  'default' => $nsassociated,
265  'tooltip' => 'namespace_association',
266  ],
267  'tagFilter' => [
268  'type' => 'tagfilter',
269  'name' => 'tagfilter',
270  'label-raw' => $this->msg( 'tag-filter' )->parse(),
271  'default' => $tagFilterVal,
272  ],
273  'username' => [
274  'type' => 'user',
275  'name' => 'username',
276  'label-message' => 'newpages-username',
277  'default' => $userText,
278  'id' => 'mw-np-username',
279  'size' => 30,
280  ],
281  'size' => [
282  'type' => 'sizefilter',
283  'name' => 'size',
284  'default' => -$max * $size,
285  ],
286  ];
287 
288  $htmlForm = HTMLForm::factory( 'ooui', $formDescriptor, $this->getContext() );
289 
290  // Store query values in hidden fields so that form submission doesn't lose them
291  foreach ( $this->opts->getUnconsumedValues() as $key => $value ) {
292  $htmlForm->addHiddenField( $key, $value );
293  }
294 
295  $htmlForm
296  ->setMethod( 'get' )
297  ->setFormIdentifier( 'newpagesform' )
298  // The form should be visible on each request (inclusive requests with submitted forms), so
299  // return always false here.
300  ->setSubmitCallback(
301  function () {
302  return false;
303  }
304  )
305  ->setSubmitText( $this->msg( 'newpages-submit' )->text() )
306  ->setWrapperLegend( $this->msg( 'newpages' )->text() )
307  ->addFooterText( Html::rawElement(
308  'div',
309  null,
310  $this->filterLinks()
311  ) )
312  ->show();
313  $out->addModuleStyles( 'mediawiki.special' );
314  }
315 
321  protected function revisionFromRcResult( stdClass $result, Title $title ) {
322  return new Revision( [
323  'comment' => CommentStore::getStore()->getComment( 'rc_comment', $result )->text,
324  'deleted' => $result->rc_deleted,
325  'user_text' => $result->rc_user_text,
326  'user' => $result->rc_user,
327  'actor' => $result->rc_actor,
328  ], 0, $title );
329  }
330 
338  public function formatRow( $result ) {
339  $title = Title::newFromRow( $result );
340 
341  // Revision deletion works on revisions,
342  // so cast our recent change row to a revision row.
343  $rev = $this->revisionFromRcResult( $result, $title );
344 
345  $classes = [];
346  $attribs = [ 'data-mw-revid' => $result->rev_id ];
347 
348  $lang = $this->getLanguage();
349  $dm = $lang->getDirMark();
350 
351  $spanTime = Html::element( 'span', [ 'class' => 'mw-newpages-time' ],
352  $lang->userTimeAndDate( $result->rc_timestamp, $this->getUser() )
353  );
354  $linkRenderer = $this->getLinkRenderer();
355  $time = $linkRenderer->makeKnownLink(
356  $title,
357  new HtmlArmor( $spanTime ),
358  [],
359  [ 'oldid' => $result->rc_this_oldid ]
360  );
361 
362  $query = $title->isRedirect() ? [ 'redirect' => 'no' ] : [];
363 
364  $plink = $linkRenderer->makeKnownLink(
365  $title,
366  null,
367  [ 'class' => 'mw-newpages-pagename' ],
368  $query
369  );
370  $linkArr = [];
371  $linkArr[] = $linkRenderer->makeKnownLink(
372  $title,
373  $this->msg( 'hist' )->text(),
374  [ 'class' => 'mw-newpages-history' ],
375  [ 'action' => 'history' ]
376  );
377  if ( ContentHandler::getForTitle( $title )->supportsDirectEditing() ) {
378  $linkArr[] = $linkRenderer->makeKnownLink(
379  $title,
380  $this->msg( 'editlink' )->text(),
381  [ 'class' => 'mw-newpages-edit' ],
382  [ 'action' => 'edit' ]
383  );
384  }
385  $links = $this->msg( 'parentheses' )->rawParams( $this->getLanguage()
386  ->pipeList( $linkArr ) )->escaped();
387 
388  $length = Html::rawElement(
389  'span',
390  [ 'class' => 'mw-newpages-length' ],
391  $this->msg( 'brackets' )->rawParams(
392  $this->msg( 'nbytes' )->numParams( $result->length )->escaped()
393  )->escaped()
394  );
395 
396  $ulink = Linker::revUserTools( $rev );
397  $comment = Linker::revComment( $rev );
398 
399  if ( $this->patrollable( $result ) ) {
400  $classes[] = 'not-patrolled';
401  }
402 
403  # Add a class for zero byte pages
404  if ( $result->length == 0 ) {
405  $classes[] = 'mw-newpages-zero-byte-page';
406  }
407 
408  # Tags, if any.
409  if ( isset( $result->ts_tags ) ) {
410  list( $tagDisplay, $newClasses ) = ChangeTags::formatSummaryRow(
411  $result->ts_tags,
412  'newpages',
413  $this->getContext()
414  );
415  $classes = array_merge( $classes, $newClasses );
416  } else {
417  $tagDisplay = '';
418  }
419 
420  # Display the old title if the namespace/title has been changed
421  $oldTitleText = '';
422  $oldTitle = Title::makeTitle( $result->rc_namespace, $result->rc_title );
423 
424  if ( !$title->equals( $oldTitle ) ) {
425  $oldTitleText = $oldTitle->getPrefixedText();
426  $oldTitleText = Html::rawElement(
427  'span',
428  [ 'class' => 'mw-newpages-oldtitle' ],
429  $this->msg( 'rc-old-title' )->params( $oldTitleText )->escaped()
430  );
431  }
432 
433  $ret = "{$time} {$dm}{$plink} {$links} {$dm}{$length} {$dm}{$ulink} {$comment} "
434  . "{$tagDisplay} {$oldTitleText}";
435 
436  // Let extensions add data
437  Hooks::run( 'NewPagesLineEnding', [ $this, &$ret, $result, &$classes, &$attribs ] );
438  $attribs = array_filter( $attribs,
439  [ Sanitizer::class, 'isReservedDataAttribute' ],
440  ARRAY_FILTER_USE_KEY
441  );
442 
443  if ( count( $classes ) ) {
444  $attribs['class'] = implode( ' ', $classes );
445  }
446 
447  return Html::rawElement( 'li', $attribs, $ret ) . "\n";
448  }
449 
456  protected function patrollable( $result ) {
457  return ( $this->getUser()->useNPPatrol() && !$result->rc_patrolled );
458  }
459 
465  protected function feed( $type ) {
466  if ( !$this->getConfig()->get( 'Feed' ) ) {
467  $this->getOutput()->addWikiMsg( 'feed-unavailable' );
468 
469  return;
470  }
471 
472  $feedClasses = $this->getConfig()->get( 'FeedClasses' );
473  if ( !isset( $feedClasses[$type] ) ) {
474  $this->getOutput()->addWikiMsg( 'feed-invalid' );
475 
476  return;
477  }
478 
479  $feed = new $feedClasses[$type](
480  $this->feedTitle(),
481  $this->msg( 'tagline' )->text(),
482  $this->getPageTitle()->getFullURL()
483  );
484 
485  $pager = new NewPagesPager( $this, $this->opts );
486  $limit = $this->opts->getValue( 'limit' );
487  $pager->mLimit = min( $limit, $this->getConfig()->get( 'FeedLimit' ) );
488 
489  $feed->outHeader();
490  if ( $pager->getNumRows() > 0 ) {
491  foreach ( $pager->mResult as $row ) {
492  $feed->outItem( $this->feedItem( $row ) );
493  }
494  }
495  $feed->outFooter();
496  }
497 
498  protected function feedTitle() {
499  $desc = $this->getDescription();
500  $code = $this->getConfig()->get( 'LanguageCode' );
501  $sitename = $this->getConfig()->get( 'Sitename' );
502 
503  return "$sitename - $desc [$code]";
504  }
505 
506  protected function feedItem( $row ) {
507  $title = Title::makeTitle( intval( $row->rc_namespace ), $row->rc_title );
508  if ( $title ) {
509  $date = $row->rc_timestamp;
510  $comments = $title->getTalkPage()->getFullURL();
511 
512  return new FeedItem(
513  $title->getPrefixedText(),
514  $this->feedItemDesc( $row ),
515  $title->getFullURL(),
516  $date,
517  $this->feedItemAuthor( $row ),
518  $comments
519  );
520  } else {
521  return null;
522  }
523  }
524 
525  protected function feedItemAuthor( $row ) {
526  return $row->rc_user_text ?? '';
527  }
528 
529  protected function feedItemDesc( $row ) {
530  $revision = Revision::newFromId( $row->rev_id );
531  if ( !$revision ) {
532  return '';
533  }
534 
535  $content = $revision->getContent();
536  if ( $content === null ) {
537  return '';
538  }
539 
540  // XXX: include content model/type in feed item?
541  return '<p>' . htmlspecialchars( $revision->getUserText() ) .
542  $this->msg( 'colon-separator' )->inContentLanguage()->escaped() .
543  htmlspecialchars( FeedItem::stripComment( $revision->getComment() ) ) .
544  "</p>\n<hr />\n<div>" .
545  nl2br( htmlspecialchars( $content->serialize() ) ) . "</div>";
546  }
547 
548  private function canAnonymousUsersCreatePages() {
549  $pm = MediaWikiServices::getInstance()->getPermissionManager();
550  return ( $pm->groupHasPermission( '*', 'createpage' ) ||
551  $pm->groupHasPermission( '*', 'createtalk' )
552  );
553  }
554 
555  protected function getGroupName() {
556  return 'changes';
557  }
558 
559  protected function getCacheTTL() {
560  return 60 * 5;
561  }
562 }
SpecialPage\getPageTitle
getPageTitle( $subpage=false)
Get a self-referential title object.
Definition: SpecialPage.php:672
SpecialPage\msg
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
Definition: SpecialPage.php:792
FeedItem
A base class for outputting syndication feeds (e.g.
Definition: FeedItem.php:33
HtmlArmor
Marks HTML that shouldn't be escaped.
Definition: HtmlArmor.php:28
Revision\newFromId
static newFromId( $id, $flags=0)
Load a page revision from a given revision ID number.
Definition: Revision.php:119
SpecialPage\getOutput
getOutput()
Get the OutputPage being used for this instance.
Definition: SpecialPage.php:719
SpecialNewpages\__construct
__construct()
Definition: SpecialNewpages.php:41
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:130
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:35
SpecialNewpages\execute
execute( $par)
Show a form for filtering namespace and username.
Definition: SpecialNewpages.php:131
FeedItem\stripComment
static stripComment( $text)
Quickie hack...
Definition: FeedItem.php:220
Linker\revComment
static revComment(Revision $rev, $local=false, $isPublic=false, $useParentheses=true)
Wrap and format the given revision's comment block, if the current user is allowed to view it.
Definition: Linker.php:1574
SpecialNewpages\canAnonymousUsersCreatePages
canAnonymousUsersCreatePages()
Definition: SpecialNewpages.php:548
ContentHandler\getForTitle
static getForTitle(Title $title)
Returns the appropriate ContentHandler singleton for the given title.
Definition: ContentHandler.php:201
IncludableSpecialPage
Shortcut to construct an includable special page.
Definition: IncludableSpecialPage.php:29
FormOptions\validateIntBounds
validateIntBounds( $name, $min, $max)
Definition: FormOptions.php:255
SpecialPage\getLanguage
getLanguage()
Shortcut to get user's language.
Definition: SpecialPage.php:749
SpecialNewpages\form
form()
Definition: SpecialNewpages.php:228
FormOptions\fetchValuesFromRequest
fetchValuesFromRequest(WebRequest $r, $optionKeys=null)
Fetch values for all options (or selected options) from the given WebRequest, making them available f...
Definition: FormOptions.php:346
SpecialNewpages\feed
feed( $type)
Output a subscription feed listing recent edits to this page.
Definition: SpecialNewpages.php:465
SpecialNewpages\setup
setup( $par)
Definition: SpecialNewpages.php:48
Revision
Definition: Revision.php:40
FormOptions\add
add( $name, $default, $type=self::AUTO)
Add an option to be handled by this FormOptions instance.
Definition: FormOptions.php:83
SpecialPage\getDescription
getDescription()
Returns the name that goes in the <h1> in the special page itself, and also the name that will be l...
Definition: SpecialPage.php:661
SpecialPage\addHelpLink
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
Definition: SpecialPage.php:828
SpecialPage\getConfig
getConfig()
Shortcut to get main config object.
Definition: SpecialPage.php:758
SpecialNewpages\getGroupName
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
Definition: SpecialNewpages.php:555
SpecialNewpages\$opts
FormOptions $opts
Definition: SpecialNewpages.php:35
Title\newFromRow
static newFromRow( $row)
Make a Title object from a DB row.
Definition: Title.php:516
SpecialNewpages\feedItem
feedItem( $row)
Definition: SpecialNewpages.php:506
$title
$title
Definition: testCompression.php:36
SpecialPage\setHeaders
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
Definition: SpecialPage.php:537
SpecialPage\getUser
getUser()
Shortcut to get the User executing this instance.
Definition: SpecialPage.php:729
SpecialNewpages\parseParams
parseParams( $par)
Definition: SpecialNewpages.php:84
Title\makeTitle
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:584
Linker\revUserTools
static revUserTools( $rev, $isPublic=false, $useParentheses=true)
Generate a user tool link cluster if the current user is allowed to view it.
Definition: Linker.php:1125
SpecialNewpages\$customFilters
array[] $customFilters
Definition: SpecialNewpages.php:37
SpecialPage\getContext
getContext()
Gets the context this SpecialPage is executed in.
Definition: SpecialPage.php:692
SpecialNewpages\feedTitle
feedTitle()
Definition: SpecialNewpages.php:498
Title\makeTitleSafe
static makeTitleSafe( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:610
$content
$content
Definition: router.php:78
SpecialNewpages\$showNavigation
$showNavigation
Definition: SpecialNewpages.php:39
SpecialPage\getRequest
getRequest()
Get the WebRequest being used for this instance.
Definition: SpecialPage.php:709
SpecialNewpages\filterLinks
filterLinks()
Definition: SpecialNewpages.php:175
NewPagesPager
Definition: NewPagesPager.php:27
SpecialNewpages\formatRow
formatRow( $result)
Format a row, providing the timestamp, links to the page/history, size, user links,...
Definition: SpecialNewpages.php:338
SpecialPage\getLinkRenderer
getLinkRenderer()
Definition: SpecialPage.php:904
$self
$self
Definition: doMaintenance.php:55
Title
Represents a title within MediaWiki.
Definition: Title.php:42
SpecialNewpages\revisionFromRcResult
revisionFromRcResult(stdClass $result, Title $title)
Definition: SpecialNewpages.php:321
SpecialNewpages
A special page that list newly created pages.
Definition: SpecialNewpages.php:31
SpecialNewpages\getCacheTTL
getCacheTTL()
Definition: SpecialNewpages.php:559
NS_USER
const NS_USER
Definition: Defines.php:62
SpecialNewpages\feedItemAuthor
feedItemAuthor( $row)
Definition: SpecialNewpages.php:525
FormOptions
Helper class to keep track of options when mixing links and form elements.
Definition: FormOptions.php:35
SpecialPage\$linkRenderer
MediaWiki Linker LinkRenderer null $linkRenderer
Definition: SpecialPage.php:67
CommentStore\getStore
static getStore()
Definition: CommentStore.php:139
Hooks\run
static run( $event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:200
HTMLForm\factory
static factory( $displayFormat,... $arguments)
Construct a HTMLForm object for given display type.
Definition: HTMLForm.php:307
SpecialPage\outputHeader
outputHeader( $summaryMessageKey='')
Outputs a summary message on top of special pages Per default the message key is the canonical name o...
Definition: SpecialPage.php:639
ChangeTags\formatSummaryRow
static formatSummaryRow( $tags, $page, IContextSource $context=null)
Creates HTML for the given tags.
Definition: ChangeTags.php:99
SpecialPage\including
including( $x=null)
Whether the special page is being evaluated via transclusion.
Definition: SpecialPage.php:230
SpecialNewpages\patrollable
patrollable( $result)
Should a specific result row provide "patrollable" links?
Definition: SpecialNewpages.php:456
SpecialNewpages\feedItemDesc
feedItemDesc( $row)
Definition: SpecialNewpages.php:529
wfArrayToCgi
wfArrayToCgi( $array1, $array2=null, $prefix='')
This function takes one or two arrays as input, and returns a CGI-style string, e....
Definition: GlobalFunctions.php:347
$type
$type
Definition: testCompression.php:50