94 parent::__construct(
'Newpages' );
95 $this->linkBatchFactory = $linkBatchFactory;
96 $this->commentStore = $commentStore;
97 $this->contentHandlerFactory = $contentHandlerFactory;
98 $this->groupPermissionsLookup = $groupPermissionsLookup;
99 $this->loadBalancer = $loadBalancer;
100 $this->revisionLookup = $revisionLookup;
101 $this->namespaceInfo = $namespaceInfo;
111 $opts->
add(
'hideliu',
false );
114 $this->userOptionsLookup->getBoolOption( $this->getUser(),
'newpageshidepatrolled' )
116 $opts->
add(
'hidebots',
false );
117 $opts->
add(
'hideredirs',
true );
120 $this->userOptionsLookup->getIntOption( $this->getUser(),
'rclimit' )
122 $opts->
add(
'offset',
'' );
123 $opts->
add(
'namespace',
'0' );
124 $opts->
add(
'username',
'' );
125 $opts->
add(
'feed',
'' );
126 $opts->
add(
'tagfilter',
'' );
127 $opts->
add(
'invert',
false );
128 $opts->
add(
'associated',
false );
129 $opts->
add(
'size-mode',
'max' );
130 $opts->
add(
'size', 0 );
132 $this->customFilters = [];
133 $this->
getHookRunner()->onSpecialNewPagesFilters( $this, $this->customFilters );
135 foreach ( $this->customFilters as $key => $params ) {
136 $opts->
add( $key, $params[
'default'] );
151 $bits = preg_split(
'/\s*,\s*/', trim( $par ) );
152 foreach ( $bits as $bit ) {
153 if ( $bit ===
'shownav' ) {
154 $this->showNavigation =
true;
156 if ( $bit ===
'hideliu' ) {
157 $this->opts->setValue(
'hideliu',
true );
159 if ( $bit ===
'hidepatrolled' ) {
160 $this->opts->setValue(
'hidepatrolled',
true );
162 if ( $bit ===
'hidebots' ) {
163 $this->opts->setValue(
'hidebots',
true );
165 if ( $bit ===
'showredirs' ) {
166 $this->opts->setValue(
'hideredirs',
false );
168 if ( is_numeric( $bit ) ) {
169 $this->opts->setValue(
'limit', intval( $bit ) );
173 if ( preg_match(
'/^limit=(\d+)$/', $bit, $m ) ) {
174 $this->opts->setValue(
'limit', intval( $m[1] ) );
177 if ( preg_match(
'/^offset=([^=]+)$/', $bit, $m ) ) {
178 $this->opts->setValue(
'offset', intval( $m[1] ) );
180 if ( preg_match(
'/^username=(.*)$/', $bit, $m ) ) {
181 $this->opts->setValue(
'username', $m[1] );
183 if ( preg_match(
'/^namespace=(.*)$/', $bit, $m ) ) {
185 if ( $ns !==
false ) {
186 $this->opts->setValue(
'namespace', $ns );
203 $this->showNavigation = !$this->
including();
204 $this->
setup( $par );
212 $feedType = $this->opts->getValue(
'feed' );
214 $this->
feed( $feedType );
219 $allValues = $this->opts->getAllValues();
220 unset( $allValues[
'feed'] );
227 $this->linkBatchFactory,
229 $this->groupPermissionsLookup,
233 $pager->mLimit = $this->opts->getValue(
'limit' );
234 $pager->mOffset = $this->opts->getValue(
'offset' );
236 if ( $pager->getNumRows() ) {
238 if ( $this->showNavigation ) {
239 $navigation = $pager->getNavigationBar();
241 $out->addHTML( $navigation . $pager->getBody() . $navigation );
243 $out->addModuleStyles(
'mediawiki.interface.helpers.styles' );
245 $out->addWikiMsg(
'specialpage-empty' );
251 $showhide = [ $this->
msg(
'show' )->escaped(), $this->
msg(
'hide' )->escaped() ];
255 'hideliu' =>
'rcshowhideliu',
256 'hidepatrolled' =>
'rcshowhidepatr',
257 'hidebots' =>
'rcshowhidebots',
258 'hideredirs' =>
'whatlinkshere-hideredirs'
260 foreach ( $this->customFilters as $key => $params ) {
261 $filters[$key] = $params[
'msg'];
266 unset( $filters[
'hideliu'] );
268 if ( !$this->
getUser()->useNPPatrol() ) {
269 unset( $filters[
'hidepatrolled'] );
273 $changed = $this->opts->getChangedValues();
274 unset( $changed[
'offset'] );
280 foreach ( $changed as $key => $value ) {
281 if ( array_key_exists( $key, $filters ) ) {
282 $changed[$key] = $changed[$key] ?
'1' :
'0';
288 foreach ( $filters as $key => $msg ) {
289 $onoff = 1 - $this->opts->getValue( $key );
294 [ $key => $onoff ] + $changed
296 $links[$key] = $this->
msg( $msg )->rawParams( $link )->escaped();
306 $this->opts->consumeValue(
'offset' );
307 $namespace = $this->opts->consumeValue(
'namespace' );
308 $username = $this->opts->consumeValue(
'username' );
309 $tagFilterVal = $this->opts->consumeValue(
'tagfilter' );
310 $nsinvert = $this->opts->consumeValue(
'invert' );
311 $nsassociated = $this->opts->consumeValue(
'associated' );
313 $size = $this->opts->consumeValue(
'size' );
314 $max = $this->opts->consumeValue(
'size-mode' ) ===
'max';
317 $ut = Title::makeTitleSafe(
NS_USER, $username );
318 $userText = $ut ? $ut->getText() :
'';
322 'type' =>
'namespaceselect',
323 'name' =>
'namespace',
324 'label-message' =>
'namespace',
325 'default' => $namespace,
330 'label-message' =>
'invert',
331 'default' => $nsinvert,
332 'tooltip' =>
'invert',
336 'name' =>
'associated',
337 'label-message' =>
'namespace_association',
338 'default' => $nsassociated,
339 'tooltip' =>
'namespace_association',
342 'type' =>
'tagfilter',
343 'name' =>
'tagfilter',
344 'label-message' =>
'tag-filter',
345 'default' => $tagFilterVal,
349 'name' =>
'username',
350 'label-message' =>
'newpages-username',
351 'default' => $userText,
352 'id' =>
'mw-np-username',
356 'type' =>
'sizefilter',
358 'default' => -$max * $size,
362 $htmlForm = HTMLForm::factory(
'ooui', $formDescriptor, $this->
getContext() );
365 foreach ( $this->opts->getUnconsumedValues() as $key => $value ) {
366 $htmlForm->addHiddenField( $key, $value );
371 ->setFormIdentifier(
'newpagesform' )
379 ->setSubmitTextMsg(
'newpages-submit' )
380 ->setWrapperLegendMsg(
'newpages' )
381 ->addFooterText( Html::rawElement(
387 $out->addModuleStyles(
'mediawiki.special' );
398 $this->commentStore->getComment(
'rc_comment', $result )
400 $revRecord->setVisibility( (
int)$result->rc_deleted );
403 (
int)$result->rc_user,
404 $result->rc_user_text
406 $revRecord->setUser( $user );
419 $title = Title::newFromRow( $result );
423 $revRecord = $this->revisionFromRcResult( $result,
$title );
426 $attribs = [
'data-mw-revid' => $result->rev_id ];
428 $lang = $this->getLanguage();
429 $dm =
$lang->getDirMark();
431 $spanTime = Html::element(
'span', [
'class' =>
'mw-newpages-time' ],
432 $lang->userTimeAndDate( $result->rc_timestamp, $this->getUser() )
434 $linkRenderer = $this->getLinkRenderer();
435 $time = $linkRenderer->makeKnownLink(
439 [
'oldid' => $result->rc_this_oldid ]
442 $query =
$title->isRedirect() ? [
'redirect' =>
'no' ] : [];
444 $plink = $linkRenderer->makeKnownLink(
447 [
'class' =>
'mw-newpages-pagename' ],
451 $linkArr[] = $linkRenderer->makeKnownLink(
453 $this->msg(
'hist' )->text(),
454 [
'class' =>
'mw-newpages-history' ],
455 [
'action' =>
'history' ]
457 if ( $this->contentHandlerFactory->getContentHandler(
$title->getContentModel() )
458 ->supportsDirectEditing()
460 $linkArr[] = $linkRenderer->makeKnownLink(
462 $this->msg(
'editlink' )->text(),
463 [
'class' =>
'mw-newpages-edit' ],
464 [
'action' =>
'edit' ]
467 $links = $this->msg(
'parentheses' )->rawParams( $this->getLanguage()
468 ->pipeList( $linkArr ) )->escaped();
470 $length = Html::rawElement(
472 [
'class' =>
'mw-newpages-length' ],
473 $this->msg(
'brackets' )->rawParams(
474 $this->msg(
'nbytes' )->numParams( $result->length )->escaped()
481 if ( $this->patrollable( $result ) ) {
482 $classes[] =
'not-patrolled';
485 # Add a class for zero byte pages
486 if ( $result->length == 0 ) {
487 $classes[] =
'mw-newpages-zero-byte-page';
491 if ( isset( $result->ts_tags ) ) {
497 $classes = array_merge( $classes, $newClasses );
502 # Display the old title if the namespace/title has been changed
504 $oldTitle = Title::makeTitle( $result->rc_namespace, $result->rc_title );
506 if ( !
$title->equals( $oldTitle ) ) {
507 $oldTitleText = $oldTitle->getPrefixedText();
508 $oldTitleText = Html::rawElement(
510 [
'class' =>
'mw-newpages-oldtitle' ],
511 $this->msg(
'rc-old-title' )->params( $oldTitleText )->escaped()
515 $ret =
"{$time} {$dm}{$plink} {$links} {$dm}{$length} {$dm}{$ulink} {$comment} "
516 .
"{$tagDisplay} {$oldTitleText}";
519 $this->getHookRunner()->onNewPagesLineEnding(
520 $this, $ret, $result, $classes, $attribs );
521 $attribs = array_filter( $attribs,
522 [ Sanitizer::class,
'isReservedDataAttribute' ],
527 $attribs[
'class'] = $classes;
530 return Html::rawElement(
'li', $attribs, $ret ) .
"\n";
540 return ( $this->getUser()->useNPPatrol() && !$result->rc_patrolled );
549 if ( !$this->getConfig()->
get(
'Feed' ) ) {
550 $this->getOutput()->addWikiMsg(
'feed-unavailable' );
555 $feedClasses = $this->getConfig()->get(
'FeedClasses' );
556 if ( !isset( $feedClasses[
$type] ) ) {
557 $this->getOutput()->addWikiMsg(
'feed-invalid' );
562 $feed =
new $feedClasses[
$type](
564 $this->msg(
'tagline' )->text(),
565 $this->getPageTitle()->getFullURL()
571 $this->linkBatchFactory,
572 $this->getHookContainer(),
573 $this->groupPermissionsLookup,
577 $limit = $this->opts->getValue(
'limit' );
578 $pager->mLimit = min( $limit, $this->getConfig()->
get(
'FeedLimit' ) );
581 if ( $pager->getNumRows() > 0 ) {
582 foreach ( $pager->mResult as $row ) {
583 $feed->outItem( $this->feedItem( $row ) );
590 $desc = $this->getDescription();
591 $code = $this->getConfig()->get(
'LanguageCode' );
592 $sitename = $this->getConfig()->get(
'Sitename' );
594 return "$sitename - $desc [$code]";
598 $title = Title::makeTitle( intval( $row->rc_namespace ), $row->rc_title );
600 $date = $row->rc_timestamp;
601 $comments =
$title->getTalkPage()->getFullURL();
604 $title->getPrefixedText(),
605 $this->feedItemDesc( $row ),
608 $this->feedItemAuthor( $row ),
617 return $row->rc_user_text ??
'';
621 $revisionRecord = $this->revisionLookup->getRevisionById( $row->rev_id );
622 if ( !$revisionRecord ) {
626 $content = $revisionRecord->getContent( SlotRecord::MAIN );
632 $revUser = $revisionRecord->getUser();
633 $revUserText = $revUser ? $revUser->getName() :
'';
634 $revComment = $revisionRecord->getComment();
635 $revCommentText = $revComment ? $revComment->text :
'';
636 return '<p>' . htmlspecialchars( $revUserText ) .
637 $this->msg(
'colon-separator' )->inContentLanguage()->escaped() .
638 htmlspecialchars( FeedItem::stripComment( $revCommentText ) ) .
639 "</p>\n<hr />\n<div>" .
640 nl2br( htmlspecialchars(
$content->serialize() ) ) .
"</div>";
644 return $this->groupPermissionsLookup->groupHasPermission(
'*',
'createpage' ) ||
645 $this->groupPermissionsLookup->groupHasPermission(
'*',
'createtalk' );
UserOptionsLookup $userOptionsLookup
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.
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.
canAnonymousUsersCreatePages()
__construct(LinkBatchFactory $linkBatchFactory, CommentStore $commentStore, IContentHandlerFactory $contentHandlerFactory, GroupPermissionsLookup $groupPermissionsLookup, ILoadBalancer $loadBalancer, RevisionLookup $revisionLookup, NamespaceInfo $namespaceInfo, UserOptionsLookup $userOptionsLookup)
LinkBatchFactory $linkBatchFactory
ILoadBalancer $loadBalancer
GroupPermissionsLookup $groupPermissionsLookup
CommentStore $commentStore
NamespaceInfo $namespaceInfo
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?
RevisionLookup $revisionLookup
feed( $type)
Output a subscription feed listing recent edits to this page.
execute( $par)
Show a form for filtering namespace and username.
IContentHandlerFactory $contentHandlerFactory
UserOptionsLookup $userOptionsLookup
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.
getUser()
Shortcut to get the User executing this instance.
LinkRenderer null $linkRenderer
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