4 * @addtogroup SpecialPage
11 function wfSpecialNewPages( $par, $sp ) {
12 $page = new NewPagesForm();
14 $page->showList( $par, $sp->including() );
18 * implements Special:Newpages
19 * @addtogroup SpecialPage
23 * Show a form for filtering namespace and username
26 * @param bool $including true if the page is being included with {{Special:Newpages}}
29 public function showList( $par, $including ) {
30 global $wgScript, $wgLang, $wgGroupPermissions, $wgRequest, $wgUser, $wgOut;
31 $sk = $wgUser->getSkin();
32 $self = SpecialPage
::getTitleFor( 'NewPages' );
35 $showhide = array( wfMsgHtml( 'show' ), wfMsgHtml( 'hide' ) );
39 if ( $wgGroupPermissions['*']['createpage'] === true ) {
40 $hidelinks['hideliu'] = 'rcshowhideliu';
42 if ( $wgUser->useNPPatrol() ) {
43 $hidelinks['hidepatrolled'] = 'rcshowhidepatr';
45 $hidelinks['hidebots'] = 'rcshowhidebots';
48 /* bool */ 'hideliu' => false,
49 /* bool */ 'hidepatrolled' => false,
50 /* bool */ 'hidebots' => false,
51 /* text */ 'namespace' => "0",
52 /* text */ 'username' => '',
53 /* int */ 'offset' => 0,
54 /* int */ 'limit' => 50,
58 // Override all values from requests, if specified
59 foreach ( $defaults as $v => $t ) {
61 $options[$v] = $wgRequest->getBool( $v, $options[$v] );
62 } elseif( is_int($t) ) {
63 $options[$v] = $wgRequest->getInt( $v, $options[$v] );
64 } elseif( is_string($t) ) {
65 $options[$v] = $wgRequest->getText( $v, $options[$v] );
69 $shownav = !$including;
71 $bits = preg_split( '/\s*,\s*/', trim( $par ) );
72 foreach ( $bits as $bit ) {
73 if ( 'shownav' == $bit )
75 if ( 'hideliu' === $bit )
76 $options['hideliu'] = true;
77 if ( 'hidepatrolled' == $bit )
78 $options['hidepatrolled'] = true;
79 if ( 'hidebots' == $bit )
80 $options['hidebots'] = true;
81 if ( is_numeric( $bit ) )
82 $options['limit'] = intval( $bit );
85 if ( preg_match( '/^limit=(\d+)$/', $bit, $m ) )
86 $options['limit'] = intval($m[1]);
87 if ( preg_match( '/^offset=(\d+)$/', $bit, $m ) )
88 $options['offset'] = intval($m[1]);
89 if ( preg_match( '/^namespace=(.*)$/', $bit, $m ) ) {
90 $ns = $wgLang->getNsIndex( $m[1] );
92 $options['namespace'] = $ns;
99 $options['username'] = '';
102 $wgOut->setSyndicated( true );
103 $wgOut->setFeedAppendQuery( "namespace={$options['namespace']}&username={$options['username']}" );
105 $feedType = $wgRequest->getVal( 'feed' );
107 wfProfileOut( __METHOD__
);
108 return $this->feed( $feedType, $options );
111 $nondefaults = array();
112 foreach ( $options as $v => $t ) {
113 if ( $v === 'offset' ) continue; # Reset offset if parameters change
114 wfAppendToArrayIfNotDefault( $v, $t, $defaults, $nondefaults );
118 foreach ( $hidelinks as $key => $msg ) {
119 $reversed = 1 - $options[$key];
120 $link = $sk->makeKnownLinkObj( $self, $showhide[$reversed],
121 wfArrayToCGI( array( $key => $reversed ), $nondefaults )
123 $links[$key] = wfMsgHtml( $msg, $link );
126 $hl = implode( ' | ', $links );
128 // Store query values in hidden fields so that form submission doesn't lose them
130 foreach ( $nondefaults as $key => $value ) {
131 if ( $key === 'namespace' ) continue;
132 if ( $key === 'username' ) continue;
133 $hidden[] = Xml
::hidden( $key, $value );
135 $hidden = implode( "\n", $hidden );
137 $form = Xml
::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) ) .
138 Xml
::hidden( 'title', $self->getPrefixedDBkey() ) .
139 Xml
::openElement( 'fieldset' ) .
140 Xml
::element( 'legend', null, wfMsg( 'newpages' ) ) .
141 Xml
::openElement( 'table', array( 'id' => 'mw-newpages-table' ) ) .
143 <td class='mw-label'>" .
144 Xml
::label( wfMsg( 'namespace' ), 'namespace' ) .
146 <td class='mw-input'>" .
147 Xml
::namespaceSelector( $options['namespace'], 'all' ) .
152 <td class='mw-label'>" .
153 Xml
::label( wfMsg( 'newpages-username' ), 'mw-np-username' ) .
155 <td class='mw-input'>" .
156 Xml
::input( 'username', 30, $options['username'], array( 'id' => 'mw-np-username' ) ) .
161 <td class='mw-submit'>" .
162 Xml
::submitButton( wfMsg( 'allpagessubmit' ) ) .
167 <td class='mw-input'>" .
171 Xml
::closeElement( 'table' ) .
172 Xml
::closeElement( 'fieldset' ) .
174 Xml
::closeElement( 'form' );
176 $wgOut->addHTML( $form );
179 $pager = new NewPagesPager( $this, array(), $options['namespace'], $options['hideliu'],
180 $options['hidepatrolled'], $options['hidebots'], $options['username'] );
181 $pager->mLimit
= $options['limit'];
182 $pager->mOffset
= $options['offset'];
184 if( $pager->getNumRows() ) {
186 ( $shownav ?
$pager->getNavigationBar() : '' ) .
188 ( $shownav ?
$pager->getNavigationBar() : '' )
191 $wgOut->addHTML( Xml
::element( 'p', null, wfMsg( 'specialpage-empty' ) ) );
196 * Format a row, providing the timestamp, links to the page/history, size, user links, and a comment
198 * @param $skin Skin to use
199 * @param $result Result row
202 public function formatRow( $result ) {
203 global $wgLang, $wgContLang, $wgUser;
204 $dm = $wgContLang->getDirMark();
208 if( is_null( $skin ) )
209 $skin = $wgUser->getSkin();
211 $title = Title
::makeTitleSafe( $result->rc_namespace
, $result->rc_title
);
212 $time = $wgLang->timeAndDate( $result->rc_timestamp
, true );
213 $plink = $skin->makeKnownLinkObj( $title, '', $this->patrollable( $result ) ?
'rcid=' . $result->rc_id
: '' );
214 $hist = $skin->makeKnownLinkObj( $title, wfMsgHtml( 'hist' ), 'action=history' );
215 $length = wfMsgExt( 'nbytes', array( 'parsemag', 'escape' ),
216 $wgLang->formatNum( htmlspecialchars( $result->length
) ) );
217 $ulink = $skin->userLink( $result->rc_user
, $result->rc_user_text
) . ' ' .
218 $skin->userToolLinks( $result->rc_user
, $result->rc_user_text
);
219 $comment = $skin->commentBlock( $result->rc_comment
);
220 $css = $this->patrollable( $result ) ?
'not-patrolled' : '';
222 return "<li class='$css'>{$time} {$dm}{$plink} ({$hist}) {$dm}[{$length}] {$dm}{$ulink} {$comment}</li>\n";
226 * Should a specific result row provide "patrollable" links?
228 * @param $result Result row
231 protected function patrollable( $result ) {
233 return ( $wgUser->useNPPatrol() && !$result->rc_patrolled
);
237 * Output a subscription feed listing recent edits to this page.
238 * @param string $type
240 protected function feed( $type, $options ) {
241 require_once 'SpecialRecentchanges.php';
243 global $wgFeed, $wgFeedClasses;
247 $wgOut->addWikiMsg( 'feed-unavailable' );
251 if( !isset( $wgFeedClasses[$type] ) ) {
253 $wgOut->addWikiMsg( 'feed-invalid' );
257 $self = SpecialPage
::getTitleFor( 'NewPages' );
258 $feed = new $wgFeedClasses[$type](
261 $self->getFullUrl() );
263 $pager = new NewPagesPager( $this, array(), $options['namespace'], $options['hideliu'],
264 $options['hidepatrolled'], $options['hidebots'], $options['username'] );
267 if( $pager->getNumRows() > 0 ) {
268 while( $row = $pager->mResult
->fetchObject() ) {
269 $feed->outItem( $this->feedItem( $row ) );
275 protected function feedTitle() {
276 global $wgContLanguageCode, $wgSitename;
277 $page = SpecialPage
::getPage( 'Newpages' );
278 $desc = $page->getDescription();
279 return "$wgSitename - $desc [$wgContLanguageCode]";
282 protected function feedItem( $row ) {
283 $title = Title
::MakeTitle( intval( $row->rc_namespace
), $row->rc_title
);
285 $date = $row->rc_timestamp
;
286 $comments = $this->stripComment( $row->rc_comment
);
289 $title->getPrefixedText(),
290 $this->feedItemDesc( $row ),
291 $title->getFullURL(),
293 $this->feedItemAuthor( $row ),
301 * Quickie hack... strip out wikilinks to more legible form from the comment.
303 function stripComment( $text ) {
304 return preg_replace( '/\[\[([^]]*\|)?([^]]+)\]\]/', '\2', $text );
307 function feedItemAuthor( $row ) {
308 return isset( $row->rc_user_text
) ?
$row->rc_user_text
: '';
311 protected function feedItemDesc( $row ) {
312 $revision = Revision
::newFromId( $row->rev_id
);
314 return '<p>' . htmlspecialchars( wfMsg( 'summary' ) ) . ': ' .
315 htmlspecialchars( $revision->getComment() ) . "</p>\n<hr />\n<div>" .
316 nl2br( htmlspecialchars( $revision->getText() ) ) . "</div>";
325 class NewPagesPager
extends ReverseChronologicalPager
{
326 private $hideliu, $hidepatrolled, $hidebots, $namespace, $user, $spTitle;
328 function __construct( $form, $conds=array(), $namespace, $hliu=false, $hpatrolled=false, $hbots=1, $user='' ) {
329 parent
::__construct();
330 $this->mForm
= $form;
331 $this->mConds
= $conds;
333 $this->namespace = ($namespace === "all") ?
false : intval($namespace);
336 $this->hideliu
= (bool)$hliu;
337 $this->hidepatrolled
= (bool)$hpatrolled;
338 $this->hidebots
= (bool)$hbots;
342 if( !isset( $this->spTitle
) )
343 $this->spTitle
= SpecialPage
::getTitleFor( 'Newpages' );
344 return $this->spTitle
;
347 function getQueryInfo() {
348 $conds = $this->mConds
;
349 $conds['rc_new'] = 1;
350 if( $this->namespace !== false ) {
351 $conds['rc_namespace'] = $this->namespace;
352 $rcIndexes = array( 'new_name_timestamp' );
354 $rcIndexes = array( 'rc_timestamp' );
356 $conds[] = 'page_id = rc_cur_id';
357 $conds['page_is_redirect'] = 0;
359 global $wgGroupPermissions, $wgUser;
360 # If anons cannot make new pages, don't query for it!
361 if( $wgGroupPermissions['*']['createpage'] && $this->hideliu
) {
362 $conds['rc_user'] = 0;
364 $title = Title
::makeTitleSafe( NS_USER
, $this->user
);
366 $conds['rc_user_text'] = $title->getText();
369 # If this user cannot see patrolled edits or they are off, don't do dumb queries!
370 if( $this->hidepatrolled
&& $wgUser->useNPPatrol() ) {
371 $conds['rc_patrolled'] = 0;
373 if( $this->hidebots
) {
374 $conds['rc_bot'] = 0;
378 $conds['rc_user_text'] = $this->user
;
382 'tables' => array( 'recentchanges', 'page' ),
383 'fields' => 'rc_namespace,rc_title, rc_cur_id, rc_user,rc_user_text,rc_comment,
384 rc_timestamp,rc_patrolled,rc_id,page_len as length, page_latest as rev_id',
386 'options' => array( 'USE INDEX' => array('recentchanges' => $rcIndexes) )
390 function getIndexField() {
391 return 'rc_timestamp';
394 function formatRow( $row ) {
395 return $this->mForm
->formatRow( $row );
398 function getStartBody() {
399 # Do a batch existence check on pages
400 $linkBatch = new LinkBatch();
401 while( $row = $this->mResult
->fetchObject() ) {
402 $linkBatch->add( NS_USER
, $row->rc_user_text
);
403 $linkBatch->add( NS_USER_TALK
, $row->rc_user_text
);
404 $linkBatch->add( $row->rc_namespace
, $row->rc_title
);
406 $linkBatch->execute();
410 function getEndBody() {