52 private $linkBatchFactory;
55 private $commentStore;
58 private $contentHandlerFactory;
61 private $groupPermissionsLookup;
64 private $loadBalancer;
67 private $revisionLookup;
70 private $namespaceInfo;
73 private $userOptionsLookup;
95 parent::__construct(
'Newpages' );
96 $this->linkBatchFactory = $linkBatchFactory;
97 $this->commentStore = $commentStore;
98 $this->contentHandlerFactory = $contentHandlerFactory;
99 $this->groupPermissionsLookup = $groupPermissionsLookup;
100 $this->loadBalancer = $loadBalancer;
101 $this->revisionLookup = $revisionLookup;
102 $this->namespaceInfo = $namespaceInfo;
103 $this->userOptionsLookup = $userOptionsLookup;
112 $opts->
add(
'hideliu',
false );
115 $this->userOptionsLookup->getBoolOption( $this->getUser(),
'newpageshidepatrolled' )
117 $opts->
add(
'hidebots',
false );
118 $opts->
add(
'hideredirs',
true );
121 $this->userOptionsLookup->getIntOption( $this->getUser(),
'rclimit' )
123 $opts->
add(
'offset',
'' );
124 $opts->
add(
'namespace',
'0' );
125 $opts->
add(
'username',
'' );
126 $opts->
add(
'feed',
'' );
127 $opts->
add(
'tagfilter',
'' );
128 $opts->
add(
'invert',
false );
129 $opts->
add(
'associated',
false );
130 $opts->
add(
'size-mode',
'max' );
131 $opts->
add(
'size', 0 );
133 $this->customFilters = [];
134 $this->
getHookRunner()->onSpecialNewPagesFilters( $this, $this->customFilters );
136 foreach ( $this->customFilters as $key => $params ) {
137 $opts->
add( $key, $params[
'default'] );
152 $bits = preg_split(
'/\s*,\s*/', trim( $par ) );
153 foreach ( $bits as $bit ) {
154 if ( $bit ===
'shownav' ) {
155 $this->showNavigation =
true;
157 if ( $bit ===
'hideliu' ) {
158 $this->opts->setValue(
'hideliu',
true );
160 if ( $bit ===
'hidepatrolled' ) {
161 $this->opts->setValue(
'hidepatrolled',
true );
163 if ( $bit ===
'hidebots' ) {
164 $this->opts->setValue(
'hidebots',
true );
166 if ( $bit ===
'showredirs' ) {
167 $this->opts->setValue(
'hideredirs',
false );
169 if ( is_numeric( $bit ) ) {
170 $this->opts->setValue(
'limit', intval( $bit ) );
174 if ( preg_match(
'/^limit=(\d+)$/', $bit, $m ) ) {
175 $this->opts->setValue(
'limit', intval( $m[1] ) );
178 if ( preg_match(
'/^offset=([^=]+)$/', $bit, $m ) ) {
179 $this->opts->setValue(
'offset', intval( $m[1] ) );
181 if ( preg_match(
'/^username=(.*)$/', $bit, $m ) ) {
182 $this->opts->setValue(
'username', $m[1] );
184 if ( preg_match(
'/^namespace=(.*)$/', $bit, $m ) ) {
186 if ( $ns !==
false ) {
187 $this->opts->setValue(
'namespace', $ns );
204 $this->showNavigation = !$this->
including();
205 $this->
setup( $par );
213 $feedType = $this->opts->getValue(
'feed' );
215 $this->
feed( $feedType );
220 $allValues = $this->opts->getAllValues();
221 unset( $allValues[
'feed'] );
225 $pager = $this->getNewPagesPager();
226 $pager->mLimit = $this->opts->getValue(
'limit' );
227 $pager->mOffset = $this->opts->getValue(
'offset' );
229 if ( $pager->getNumRows() ) {
231 if ( $this->showNavigation ) {
232 $navigation = $pager->getNavigationBar();
234 $out->addHTML( $navigation . $pager->getBody() . $navigation );
236 $out->addModuleStyles(
'mediawiki.interface.helpers.styles' );
238 $out->addWikiMsg(
'specialpage-empty' );
244 $showhide = [ $this->
msg(
'show' )->escaped(), $this->
msg(
'hide' )->escaped() ];
248 'hideliu' =>
'newpages-showhide-registered',
249 'hidepatrolled' =>
'newpages-showhide-patrolled',
250 'hidebots' =>
'newpages-showhide-bots',
251 'hideredirs' =>
'newpages-showhide-redirect'
253 foreach ( $this->customFilters as $key => $params ) {
254 $filters[$key] = $params[
'msg'];
258 if ( !$this->canAnonymousUsersCreatePages() ) {
259 unset( $filters[
'hideliu'] );
261 if ( !$this->
getUser()->useNPPatrol() ) {
262 unset( $filters[
'hidepatrolled'] );
266 $changed = $this->opts->getChangedValues();
267 unset( $changed[
'offset'] );
273 foreach ( $changed as $key => $value ) {
274 if ( array_key_exists( $key, $filters ) ) {
275 $changed[$key] = $changed[$key] ?
'1' :
'0';
281 foreach ( $filters as $key => $msg ) {
282 $onoff = 1 - $this->opts->getValue( $key );
283 $link = $linkRenderer->makeLink(
287 [ $key => $onoff ] + $changed
289 $links[$key] = $this->
msg( $msg )->rawParams( $link )->escaped();
299 $this->opts->consumeValue(
'offset' );
300 $namespace = $this->opts->consumeValue(
'namespace' );
301 $username = $this->opts->consumeValue(
'username' );
302 $tagFilterVal = $this->opts->consumeValue(
'tagfilter' );
303 $nsinvert = $this->opts->consumeValue(
'invert' );
304 $nsassociated = $this->opts->consumeValue(
'associated' );
306 $size = $this->opts->consumeValue(
'size' );
307 $max = $this->opts->consumeValue(
'size-mode' ) ===
'max';
310 $ut = Title::makeTitleSafe(
NS_USER, $username );
311 $userText = $ut ? $ut->getText() :
'';
315 'type' =>
'namespaceselect',
316 'name' =>
'namespace',
317 'label-message' =>
'namespace',
318 'default' => $namespace,
323 'label-message' =>
'invert',
324 'default' => $nsinvert,
325 'tooltip' =>
'invert',
329 'name' =>
'associated',
330 'label-message' =>
'namespace_association',
331 'default' => $nsassociated,
332 'tooltip' =>
'namespace_association',
335 'type' =>
'tagfilter',
336 'name' =>
'tagfilter',
337 'label-message' =>
'tag-filter',
338 'default' => $tagFilterVal,
342 'name' =>
'username',
343 'label-message' =>
'newpages-username',
344 'default' => $userText,
345 'id' =>
'mw-np-username',
349 'type' =>
'sizefilter',
351 'default' => ( $max ? -1 : 1 ) * $size,
355 $htmlForm = HTMLForm::factory(
'ooui', $formDescriptor, $this->
getContext() );
358 foreach ( $this->opts->getUnconsumedValues() as $key => $value ) {
359 $htmlForm->addHiddenField( $key, $value );
364 ->setFormIdentifier(
'newpagesform' )
372 ->setSubmitTextMsg(
'newpages-submit' )
373 ->setWrapperLegendMsg(
'newpages' )
374 ->addFooterText( Html::rawElement(
380 $out->addModuleStyles(
'mediawiki.special' );
391 $this->commentStore->getComment(
'rc_comment', $result )
393 $revRecord->setVisibility( (
int)$result->rc_deleted );
396 (
int)$result->rc_user,
397 $result->rc_user_text
399 $revRecord->setUser( $user );
412 $title = Title::newFromRow( $result );
416 $revRecord = $this->revisionFromRcResult( $result,
$title );
419 $attribs = [
'data-mw-revid' => $result->rev_id ];
421 $lang = $this->getLanguage();
422 $dm =
$lang->getDirMark();
424 $spanTime = Html::element(
'span', [
'class' =>
'mw-newpages-time' ],
425 $lang->userTimeAndDate( $result->rc_timestamp, $this->getUser() )
427 $linkRenderer = $this->getLinkRenderer();
428 $time = $linkRenderer->makeKnownLink(
432 [
'oldid' => $result->rc_this_oldid ]
435 $query =
$title->isRedirect() ? [
'redirect' =>
'no' ] : [];
437 $plink = $linkRenderer->makeKnownLink(
440 [
'class' =>
'mw-newpages-pagename' ],
444 $linkArr[] = $linkRenderer->makeKnownLink(
446 $this->msg(
'hist' )->text(),
447 [
'class' =>
'mw-newpages-history' ],
448 [
'action' =>
'history' ]
450 if ( $this->contentHandlerFactory->getContentHandler(
$title->getContentModel() )
451 ->supportsDirectEditing()
453 $linkArr[] = $linkRenderer->makeKnownLink(
455 $this->msg(
'editlink' )->text(),
456 [
'class' =>
'mw-newpages-edit' ],
457 [
'action' =>
'edit' ]
460 $links = $this->msg(
'parentheses' )->rawParams( $this->getLanguage()
461 ->pipeList( $linkArr ) )->escaped();
463 $length = Html::rawElement(
465 [
'class' =>
'mw-newpages-length' ],
466 $this->msg(
'brackets' )->rawParams(
467 $this->msg(
'nbytes' )->numParams( $result->length )->escaped()
474 if ( $this->patrollable( $result ) ) {
475 $classes[] =
'not-patrolled';
478 # Add a class for zero byte pages
479 if ( $result->length == 0 ) {
480 $classes[] =
'mw-newpages-zero-byte-page';
484 if ( isset( $result->ts_tags ) ) {
490 $classes = array_merge( $classes, $newClasses );
495 # Display the old title if the namespace/title has been changed
497 $oldTitle = Title::makeTitle( $result->rc_namespace, $result->rc_title );
499 if ( !
$title->equals( $oldTitle ) ) {
500 $oldTitleText = $oldTitle->getPrefixedText();
501 $oldTitleText = Html::rawElement(
503 [
'class' =>
'mw-newpages-oldtitle' ],
504 $this->msg(
'rc-old-title' )->params( $oldTitleText )->escaped()
508 $ret =
"{$time} {$dm}{$plink} {$links} {$dm}{$length} {$dm}{$ulink} {$comment} "
509 .
"{$tagDisplay} {$oldTitleText}";
512 $this->getHookRunner()->onNewPagesLineEnding(
513 $this, $ret, $result, $classes, $attribs );
514 $attribs = array_filter( $attribs,
515 [ Sanitizer::class,
'isReservedDataAttribute' ],
520 $attribs[
'class'] = $classes;
523 return Html::rawElement(
'li', $attribs, $ret ) .
"\n";
526 private function getNewPagesPager() {
529 $this->groupPermissionsLookup,
530 $this->getHookContainer(),
531 $this->linkBatchFactory,
533 $this->namespaceInfo,
545 return ( $this->
getUser()->useNPPatrol() && !$result->rc_patrolled );
554 if ( !$this->getConfig()->
get( MainConfigNames::Feed ) ) {
555 $this->getOutput()->addWikiMsg(
'feed-unavailable' );
560 $feedClasses = $this->getConfig()->get( MainConfigNames::FeedClasses );
561 if ( !isset( $feedClasses[
$type] ) ) {
562 $this->getOutput()->addWikiMsg(
'feed-invalid' );
567 $feed =
new $feedClasses[
$type](
569 $this->msg(
'tagline' )->text(),
570 $this->getPageTitle()->getFullURL()
573 $pager = $this->getNewPagesPager();
574 $limit = $this->opts->getValue(
'limit' );
575 $pager->mLimit = min( $limit, $this->getConfig()->
get( MainConfigNames::FeedLimit ) );
578 if ( $pager->getNumRows() > 0 ) {
579 foreach ( $pager->mResult as $row ) {
580 $feed->outItem( $this->feedItem( $row ) );
587 $desc = $this->getDescription();
588 $code = $this->getConfig()->get( MainConfigNames::LanguageCode );
589 $sitename = $this->getConfig()->get( MainConfigNames::Sitename );
591 return "$sitename - $desc [$code]";
595 $title = Title::makeTitle( intval( $row->rc_namespace ), $row->rc_title );
597 $date = $row->rc_timestamp;
598 $comments =
$title->getTalkPage()->getFullURL();
601 $title->getPrefixedText(),
602 $this->feedItemDesc( $row ),
605 $this->feedItemAuthor( $row ),
614 return $row->rc_user_text ??
'';
618 $revisionRecord = $this->revisionLookup->getRevisionById( $row->rev_id );
619 if ( !$revisionRecord ) {
623 $content = $revisionRecord->getContent( SlotRecord::MAIN );
629 $revUser = $revisionRecord->getUser();
630 $revUserText = $revUser ? $revUser->getName() :
'';
631 $revComment = $revisionRecord->getComment();
632 $revCommentText = $revComment ? $revComment->text :
'';
633 return '<p>' . htmlspecialchars( $revUserText ) .
634 $this->msg(
'colon-separator' )->inContentLanguage()->escaped() .
635 htmlspecialchars( FeedItem::stripComment( $revCommentText ) ) .
636 "</p>\n<hr />\n<div>" .
637 nl2br( htmlspecialchars(
$content->serialize() ) ) .
"</div>";
640 private function canAnonymousUsersCreatePages() {
641 return $this->groupPermissionsLookup->groupHasPermission(
'*',
'createpage' ) ||
642 $this->groupPermissionsLookup->groupHasPermission(
'*',
'createtalk' );
wfArrayToCgi( $array1, $array2=null, $prefix='')
This function takes one or two arrays as input, and returns a CGI-style string, e....
A base class for outputting syndication feeds (e.g.
Marks HTML that shouldn't be escaped.
Shortcut to construct an includable special page.
static revComment(RevisionRecord $revRecord, $local=false, $isPublic=false, $useParentheses=true)
Wrap and format the given revision's comment block, if the current user is allowed to view it.
static revUserTools(RevisionRecord $revRecord, $isPublic=false, $useParentheses=true)
Generate a user tool link cluster if the current user is allowed to view it.
A class containing constants representing the names of configuration variables.
This is a utility class for dealing with namespaces that encodes all the "magic" behaviors of them ba...
A special page that list newly created pages.
__construct(LinkBatchFactory $linkBatchFactory, CommentStore $commentStore, IContentHandlerFactory $contentHandlerFactory, GroupPermissionsLookup $groupPermissionsLookup, ILoadBalancer $loadBalancer, RevisionLookup $revisionLookup, NamespaceInfo $namespaceInfo, UserOptionsLookup $userOptionsLookup)
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
patrollable( $result)
Should a specific result row provide "patrollable" links?
feed( $type)
Output a subscription feed listing recent edits to this page.
execute( $par)
Show a form for filtering namespace and username.
formatRow( $result)
Format a row, providing the timestamp, links to the page/history, size, user links,...
revisionFromRcResult(stdClass $result, Title $title)
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.
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.
getLanguage()
Shortcut to get user's language.
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
including( $x=null)
Whether the special page is being evaluated via transclusion.
Represents a title within MediaWiki.
if(!isset( $args[0])) $lang