* remove end of line whitespace
[lhc/web/wiklou.git] / includes / SpecialNewpages.php
1 <?php
2 /**
3 *
4 * @addtogroup SpecialPage
5 */
6
7
8 /**
9 * Start point
10 */
11 function wfSpecialNewPages( $par ) {
12 $page = new NewPagesForm();
13
14 $page->showList( $par );
15 }
16
17 /**
18 * implements Special:Newpages
19 * @addtogroup SpecialPage
20 */
21 class NewPagesForm {
22 /**
23 * Show a form for filtering namespace and username
24 *
25 * @return string
26 */
27 public function showList() {
28 global $wgScript, $wgContLang, $wgGroupPermissions, $wgRequest, $wgUser, $wgOut;
29 $sk = $wgUser->getSkin();
30 $align = $wgContLang->isRTL() ? 'left' : 'right';
31 $self = SpecialPage::getTitleFor( 'NewPages' );
32
33 // show/hide links
34 $showhide = array( wfMsgHtml( 'show' ), wfMsgHtml( 'hide' ));
35
36 $hidelinks = array();
37
38 if ( $wgGroupPermissions['*']['createpage'] === true ) {
39 $hidelinks['hideliu'] = 'rcshowhideliu';
40 }
41 if ( $wgUser->useNPPatrol() ) {
42 $hidelinks['hidepatrolled'] = 'rcshowhidepatr';
43 }
44 $hidelinks['hidebots'] = 'rcshowhidebots';
45
46 $defaults = array(
47 /* bool */ 'hideliu' => false,
48 /* bool */ 'hidepatrolled' => false,
49 /* bool */ 'hidebots' => false,
50 /* text */ 'namespace' => "0",
51 /* text */ 'username' => '',
52 /* int */ 'offset' => 0,
53 /* int */ 'limit' => 50,
54 );
55 $options = $defaults;
56
57 // Override all values from requests, if specified
58 foreach ( $defaults as $v => $t ) {
59 if ( is_bool($t) ) {
60 $options[$v] = $wgRequest->getBool( $v, $options[$v] );
61 } elseif( is_int($t) ) {
62 $options[$v] = $wgRequest->getInt( $v, $options[$v] );
63 } elseif( is_string($t) ) {
64 $options[$v] = $wgRequest->getText( $v, $options[$v] );
65 }
66 }
67
68 $wgOut->setSyndicated( true );
69 $wgOut->setFeedAppendQuery( "namespace={$options['namespace']}&username={$options['username']}" );
70
71 $feedType = $wgRequest->getVal( 'feed' );
72 if( $feedType ) {
73 wfProfileOut( __METHOD__ );
74 return $this->feed( $feedType, $options );
75 }
76
77 $nondefaults = array();
78 foreach ( $options as $v => $t ) {
79 if ( $v === 'offset' ) continue; # Reset offset if parameters change
80 wfAppendToArrayIfNotDefault( $v, $t, $defaults, $nondefaults );
81 }
82
83 $links = array();
84 foreach ( $hidelinks as $key => $msg ) {
85 $reversed = 1 - $options[$key];
86 $link = $sk->makeKnownLinkObj( $self, $showhide[$reversed],
87 wfArrayToCGI( array( $key => $reversed ), $nondefaults )
88 );
89 $links[$key] = wfMsgHtml( $msg, $link );
90 }
91
92 $hl = implode( ' | ', $links );
93
94 // Store query values in hidden fields so that form submission doesn't lose them
95 $hidden = array();
96 foreach ( $nondefaults as $key => $value ) {
97 if ( $key === 'namespace' ) continue;
98 if ( $key === 'username' ) continue;
99 $hidden[] = Xml::hidden( $key, $value );
100 }
101 $hidden = implode( "\n", $hidden );
102
103 $form = Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) ) .
104 Xml::hidden( 'title', $self->getPrefixedDBkey() ) .
105 Xml::openElement( 'fieldset' ) .
106 Xml::element( 'legend', null, wfMsg( 'newpages' ) ) .
107 Xml::openElement( 'table', array( 'id' => 'mw-newpages-table' ) ) .
108 "<tr>
109 <td align=\"$align\">" .
110 Xml::label( wfMsg( 'namespace' ), 'namespace' ) .
111 "</td>
112 <td>" .
113 Xml::namespaceSelector( $options['namespace'], 'all' ) .
114 "</td>
115 </tr>
116 <tr>
117 <td align=\"$align\">" .
118 Xml::label( wfMsg( 'newpages-username' ), 'mw-np-username' ) .
119 "</td>
120 <td>" .
121 Xml::input( 'username', 30, $options['username'], array( 'id' => 'mw-np-username' ) ) .
122 "</td>
123 </tr>
124 <tr> <td></td>
125 <td>" .
126 Xml::submitButton( wfMsg( 'allpagessubmit' ) ) .
127 "</td>
128 </tr>" .
129 "<tr>
130 <td></td>
131 <td>" .
132 $hl .
133 "</td>
134 </tr>" .
135 Xml::closeElement( 'table' ) .
136 Xml::closeElement( 'fieldset' ) .
137 $hidden .
138 Xml::closeElement( 'form' );
139
140 $wgOut->addHTML( $form );
141
142 $pager = new NewPagesPager( $this, array(), $options['namespace'], $options['hideliu'],
143 $options['hidepatrolled'], $options['hidebots'], $options['username'] );
144
145 if( $pager->getNumRows() ) {
146 $wgOut->addHTML( $pager->getNavigationBar() .
147 $pager->getStartBody() .
148 $pager->getBody() .
149 $pager->getEndBody() .
150 $pager->getNavigationBar() );
151 } else {
152 $wgOut->addHTML( '<p>' . wfMsgHtml( 'specialpage-empty' ) . '</p>' );
153 }
154 }
155
156 /**
157 * Format a row, providing the timestamp, links to the page/history, size, user links, and a comment
158 *
159 * @param $skin Skin to use
160 * @param $result Result row
161 * @return string
162 */
163 public function formatRow( $result ) {
164 global $wgLang, $wgContLang, $wgUser;
165 $dm = $wgContLang->getDirMark();
166
167 static $skin=null;
168
169 if( is_null( $skin ) )
170 $skin = $wgUser->getSkin();
171
172 $title = Title::makeTitleSafe( $result->rc_namespace, $result->rc_title );
173 $time = $wgLang->timeAndDate( $result->rc_timestamp, true );
174 $plink = $skin->makeKnownLinkObj( $title, '', $this->patrollable( $result ) ? 'rcid=' . $result->rc_id : '' );
175 $hist = $skin->makeKnownLinkObj( $title, wfMsgHtml( 'hist' ), 'action=history' );
176 $length = wfMsgExt( 'nbytes', array( 'parsemag', 'escape' ),
177 $wgLang->formatNum( htmlspecialchars( $result->length ) ) );
178 $ulink = $skin->userLink( $result->rc_user, $result->rc_user_text ) . ' ' .
179 $skin->userToolLinks( $result->rc_user, $result->rc_user_text );
180 $comment = $skin->commentBlock( $result->rc_comment );
181 $css = $this->patrollable( $result ) ? 'not-patrolled' : '';
182
183 return "<li class='$css'>{$time} {$dm}{$plink} ({$hist}) {$dm}[{$length}] {$dm}{$ulink} {$comment}</li>";
184 }
185
186 /**
187 * Should a specific result row provide "patrollable" links?
188 *
189 * @param $result Result row
190 * @return bool
191 */
192 protected function patrollable( $result ) {
193 global $wgUser;
194 return ( $wgUser->useNPPatrol() && !$result->rc_patrolled );
195 }
196
197 /**
198 * Output a subscription feed listing recent edits to this page.
199 * @param string $type
200 */
201 protected function feed( $type, $options ) {
202 require_once 'SpecialRecentchanges.php';
203
204 global $wgFeed, $wgFeedClasses;
205
206 if ( !$wgFeed ) {
207 global $wgOut;
208 $wgOut->addWikiMsg( 'feed-unavailable' );
209 return;
210 }
211
212 if( !isset( $wgFeedClasses[$type] ) ) {
213 global $wgOut;
214 $wgOut->addWikiMsg( 'feed-invalid' );
215 return;
216 }
217
218 $self = SpecialPage::getTitleFor( 'NewPages' );
219 $feed = new $wgFeedClasses[$type](
220 $this->feedTitle(),
221 wfMsg( 'tagline' ),
222 $self->getFullUrl() );
223
224 $pager = new NewPagesPager( $this, array(), $options['namespace'], $options['hideliu'],
225 $options['hidepatrolled'], $options['hidebots'], $options['username'] );
226
227 $feed->outHeader();
228 if( $pager->getNumRows() > 0 ) {
229 while( $row = $pager->mResult->fetchObject() ) {
230 $feed->outItem( $this->feedItem( $row ) );
231 }
232 }
233 $feed->outFooter();
234 }
235
236 protected function feedTitle() {
237 global $wgContLanguageCode, $wgSitename;
238 $page = SpecialPage::getPage( 'Newpages' );
239 $desc = $page->getDescription();
240 return "$wgSitename - $desc [$wgContLanguageCode]";
241 }
242
243 protected function feedItem( $row ) {
244 $title = Title::MakeTitle( intval( $row->rc_namespace ), $row->rc_title );
245 if( $title ) {
246 $date = $row->rc_timestamp;
247 $comments = $this->stripComment( $row->rc_comment );
248
249 return new FeedItem(
250 $title->getPrefixedText(),
251 $this->feedItemDesc( $row ),
252 $title->getFullURL(),
253 $date,
254 $this->feedItemAuthor( $row ),
255 $comments);
256 } else {
257 return NULL;
258 }
259 }
260
261 /**
262 * Quickie hack... strip out wikilinks to more legible form from the comment.
263 */
264 function stripComment( $text ) {
265 return preg_replace( '/\[\[([^]]*\|)?([^]]+)\]\]/', '\2', $text );
266 }
267
268 function feedItemAuthor( $row ) {
269 return isset( $row->rc_user_text ) ? $row->rc_user_text : '';
270 }
271
272 protected function feedItemDesc( $row ) {
273 $revision = Revision::newFromId( $row->rev_id );
274 if( $revision ) {
275 return '<p>' . htmlspecialchars( wfMsg( 'summary' ) ) . ': ' .
276 htmlspecialchars( $revision->getComment() ) . "</p>\n<hr />\n<div>" .
277 nl2br( htmlspecialchars( $revision->getText() ) ) . "</div>";
278 }
279 return '';
280 }
281 }
282
283 /**
284 * @addtogroup Pager
285 */
286 class NewPagesPager extends ReverseChronologicalPager {
287 private $hideliu, $hidepatrolled, $hidebots, $namespace, $user;
288
289 function __construct( $form, $conds=array(), $namespace, $hliu=false, $hpatrolled=false, $hbots=1, $user='' ) {
290 parent::__construct();
291 $this->mForm = $form;
292 $this->mConds = $conds;
293
294 $this->namespace = ($namespace === "all") ? false : intval($namespace);
295 $this->user = $user;
296
297 $this->hideliu = (bool)$hliu;
298 $this->hidepatrolled = (bool)$hpatrolled;
299 $this->hidebots = (bool)$hbots;
300 }
301
302 function getQueryInfo() {
303 $conds = $this->mConds;
304 $conds['rc_new'] = 1;
305 if( $this->namespace !== false ) {
306 $conds['rc_namespace'] = $this->namespace;
307 $rcIndexes = array( 'new_name_timestamp', 'rc_timestamp', 'rc_user_text' );
308 } else {
309 $rcIndexes = array( 'rc_timestamp', 'rc_user_text' );
310 }
311 $conds[] = 'page_id = rc_cur_id';
312 $conds['page_is_redirect'] = 0;
313
314 global $wgGroupPermissions, $wgUser;
315 # If anons cannot make new pages, don't query for it!
316 if( $wgGroupPermissions['*']['createpage'] && $this->hideliu ) {
317 $conds['rc_user'] = 0;
318 } else {
319 $title = Title::makeTitleSafe( NS_USER, $this->user );
320 if( $title ) {
321 $conds['rc_user_text'] = $title->getText();
322 }
323 }
324 # If this user cannot see patrolled edits or they are off, don't do dumb queries!
325 if( $this->hidepatrolled && $wgUser->useNPPatrol() ) {
326 $conds['rc_patrolled'] = 0;
327 }
328 if( $this->hidebots ) {
329 $conds['rc_bot'] = 0;
330 }
331
332 if( $this->user ) {
333 $conds['rc_user_text'] = $this->user;
334 }
335
336 return array(
337 'tables' => array( 'recentchanges', 'page' ),
338 'fields' => 'rc_namespace,rc_title, rc_cur_id, rc_user,rc_user_text,rc_comment,
339 rc_timestamp,rc_patrolled,rc_id,page_len as length, page_latest as rev_id',
340 'conds' => $conds,
341 'options' => array( 'USE INDEX' => array('recentchanges' => $rcIndexes) )
342 );
343 }
344
345 function getIndexField() {
346 return 'rc_timestamp';
347 }
348
349 function formatRow( $row ) {
350 return $this->mForm->formatRow( $row );
351 }
352
353 function getStartBody() {
354 # Do a batch existence check on pages
355 $linkBatch = new LinkBatch();
356 while( $row = $this->mResult->fetchObject() ) {
357 $linkBatch->add( NS_USER, $row->rc_user_text );
358 $linkBatch->add( NS_USER_TALK, $row->rc_user_text );
359 $linkBatch->add( $row->rc_namespace, $row->rc_title );
360 }
361 $linkBatch->execute();
362 return "<ul>";
363 }
364
365 function getEndBody() {
366 return "</ul>";
367 }
368 }