X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2Fspecials%2FSpecialWatchlist.php;h=b20b33117b2a565483085fc43c412da802c9f02a;hb=69f16b7a69f9491b695ba0c9dfab7a7bdcb591d7;hp=1d76e3610652d45bcc216bb2b49d45954d053651;hpb=70d904b5bd04deb758272fc897d52e83a4141104;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/specials/SpecialWatchlist.php b/includes/specials/SpecialWatchlist.php index 1d76e36106..b20b33117b 100644 --- a/includes/specials/SpecialWatchlist.php +++ b/includes/specials/SpecialWatchlist.php @@ -32,6 +32,8 @@ use Wikimedia\Rdbms\IDatabase; * @ingroup SpecialPage */ class SpecialWatchlist extends ChangesListSpecialPage { + private $maxDays; + public function __construct( $page = 'Watchlist', $restriction = 'viewmywatchlist' ) { parent::__construct( $page, $restriction ); @@ -93,6 +95,20 @@ class SpecialWatchlist extends ChangesListSpecialPage { } parent::execute( $subpage ); + + if ( $this->isStructuredFilterUiEnabled() ) { + $output->addJsConfigVars( 'wgStructuredChangeFiltersLiveUpdateSupported', false ); + $output->addJsConfigVars( + 'wgStructuredChangeFiltersSavedQueriesPreferenceName', + 'rcfilters-wl-saved-queries' + ); + } + } + + protected function isStructuredFilterUiEnabled() { + return parent::isStructuredFilterUiEnabled() + && ( $this->getConfig()->get( 'StructuredChangeFiltersOnWatchlist' ) + || $this->getRequest()->getBool( 'rcfilters' ) ); } /** @@ -126,6 +142,47 @@ class SpecialWatchlist extends ChangesListSpecialPage { protected function registerFilters() { parent::registerFilters(); + $this->registerFilterGroup( new ChangesListStringOptionsFilterGroup( [ + 'name' => 'watchlistactivity', + 'title' => 'rcfilters-filtergroup-watchlistactivity', + 'class' => ChangesListStringOptionsFilterGroup::class, + 'priority' => 3, + 'isFullCoverage' => true, + 'filters' => [ + [ + 'name' => 'unseen', + 'label' => 'rcfilters-filter-watchlistactivity-unseen-label', + 'description' => 'rcfilters-filter-watchlistactivity-unseen-description', + 'cssClassSuffix' => 'watchedunseen', + 'isRowApplicableCallable' => function ( $ctx, $rc ) { + $changeTs = $rc->getAttribute( 'rc_timestamp' ); + $lastVisitTs = $rc->getAttribute( 'wl_notificationtimestamp' ); + return $changeTs >= $lastVisitTs; + }, + ], + [ + 'name' => 'seen', + 'label' => 'rcfilters-filter-watchlistactivity-seen-label', + 'description' => 'rcfilters-filter-watchlistactivity-seen-description', + 'cssClassSuffix' => 'watchedseen', + 'isRowApplicableCallable' => function ( $ctx, $rc ) { + $changeTs = $rc->getAttribute( 'rc_timestamp' ); + $lastVisitTs = $rc->getAttribute( 'wl_notificationtimestamp' ); + return $changeTs < $lastVisitTs; + } + ], + ], + 'default' => ChangesListStringOptionsFilterGroup::NONE, + 'queryCallable' => function ( $specialPageClassName, $context, $dbr, + &$tables, &$fields, &$conds, &$query_options, &$join_conds, $selectedValues ) { + if ( $selectedValues === [ 'seen' ] ) { + $conds[] = 'rc_timestamp < wl_notificationtimestamp'; + } elseif ( $selectedValues === [ 'unseen' ] ) { + $conds[] = 'rc_timestamp >= wl_notificationtimestamp'; + } + } + ] ) ); + $user = $this->getUser(); $significance = $this->getFilterGroup( 'significance' ); @@ -172,12 +229,14 @@ class SpecialWatchlist extends ChangesListSpecialPage { $opts->add( 'days', $user->getOption( 'watchlistdays' ), FormOptions::FLOAT ); $opts->add( 'extended', $user->getBoolOption( 'extendwatchlist' ) ); + $opts->add( 'limit', $user->getIntOption( 'wllimit' ), FormOptions::INT ); return $opts; } public function validateOptions( FormOptions $opts ) { $opts->validateBounds( 'days', 0, $this->maxDays ); + $opts->validateIntBounds( 'limit', 0, 5000 ); parent::validateOptions( $opts ); } @@ -300,7 +359,7 @@ class SpecialWatchlist extends ChangesListSpecialPage { $query_options = array_merge( [ 'ORDER BY' => 'rc_timestamp DESC', - 'LIMIT' => $user->getIntOption( 'wllimit' ) + 'LIMIT' => $opts['limit'] ], $query_options ); $join_conds = array_merge( [ @@ -458,6 +517,11 @@ class SpecialWatchlist extends ChangesListSpecialPage { } $s = $list->beginRecentChangesList(); + + if ( $this->isStructuredFilterUiEnabled() ) { + $s .= $this->makeLegend(); + } + $userShowHiddenCats = $this->getUser()->getBoolOption( 'showhiddencats' ); $counter = 1; foreach ( $rows as $obj ) { @@ -518,6 +582,24 @@ class SpecialWatchlist extends ChangesListSpecialPage { $this->setTopText( $opts ); + $form = ''; + + $form .= Xml::openElement( 'form', [ + 'method' => 'get', + 'action' => wfScript(), + 'id' => 'mw-watchlist-form' + ] ); + $form .= Html::hidden( 'title', $this->getPageTitle()->getPrefixedText() ); + $form .= Xml::fieldset( + $this->msg( 'watchlist-options' )->text(), + false, + [ 'id' => 'mw-watchlist-options', 'class' => 'cloptions' ] + ); + + if ( !$this->isStructuredFilterUiEnabled() ) { + $form .= $this->makeLegend(); + } + $lang = $this->getLanguage(); if ( $opts['days'] > 0 ) { $days = $opts['days']; @@ -525,16 +607,23 @@ class SpecialWatchlist extends ChangesListSpecialPage { $days = $this->maxDays; } $timestamp = wfTimestampNow(); - $wlInfo = $this->msg( 'wlnote' )->numParams( $numRows, round( $days * 24 ) )->params( - $lang->userDate( $timestamp, $user ), $lang->userTime( $timestamp, $user ) - )->parse() . "
\n"; + $wlInfo = Html::rawElement( + 'span', + [ 'class' => 'wlinfo' ], + $this->msg( 'wlnote' )->numParams( $numRows, round( $days * 24 ) )->params( + $lang->userDate( $timestamp, $user ), $lang->userTime( $timestamp, $user ) + )->parse() + ) . "
\n"; $nondefaults = $opts->getChangedValues(); - $cutofflinks = $this->msg( 'wlshowtime' ) . ' ' . $this->cutoffselector( $opts ); + $cutofflinks = Html::rawElement( + 'span', + [ 'class' => 'cldays cloption' ], + $this->msg( 'wlshowtime' ) . ' ' . $this->cutoffselector( $opts ) + ); # Spit out some control panel links $links = []; - $context = $this->getContext(); $namesOfDisplayedFilters = []; foreach ( $this->getFilterGroups() as $groupName => $group ) { if ( !$group->isPerGroupRequestParameter() ) { @@ -545,7 +634,8 @@ class SpecialWatchlist extends ChangesListSpecialPage { $nondefaults, $filter->getShowHide(), $filterName, - $opts[$filterName] + $opts[$filterName], + $filter->isFeatureAvailableOnStructuredUi( $this ) ); } } @@ -562,17 +652,19 @@ class SpecialWatchlist extends ChangesListSpecialPage { unset( $hiddenFields[$filterName] ); } - # Create output - $form = ''; - # Namespace filter and put the whole form together. $form .= $wlInfo; $form .= $cutofflinks; - $form .= $this->msg( 'watchlist-hide' ) . + $form .= Html::rawElement( + 'span', + [ 'class' => 'clshowhide' ], + $this->msg( 'watchlist-hide' ) . $this->msg( 'colon-separator' )->escaped() . - implode( ' ', $links ); + implode( ' ', $links ) + ); $form .= "\n
\n"; - $form .= Html::namespaceSelector( + + $namespaceForm = Html::namespaceSelector( [ 'selected' => $opts['namespace'], 'all' => '', @@ -583,27 +675,66 @@ class SpecialWatchlist extends ChangesListSpecialPage { 'class' => 'namespaceselector', ] ) . "\n"; - $form .= '' . Xml::checkLabel( + $namespaceForm .= '' . Xml::checkLabel( $this->msg( 'invert' )->text(), 'invert', 'nsinvert', $opts['invert'], [ 'title' => $this->msg( 'tooltip-invert' )->text() ] ) . "\n"; - $form .= '' . Xml::checkLabel( + $namespaceForm .= '' . Xml::checkLabel( $this->msg( 'namespace_association' )->text(), 'associated', 'nsassociated', $opts['associated'], [ 'title' => $this->msg( 'tooltip-namespace_association' )->text() ] ) . "\n"; - $form .= Xml::submitButton( $this->msg( 'watchlist-submit' )->text() ) . "\n"; + $form .= Html::rawElement( + 'span', + [ 'class' => 'namespaceForm cloption' ], + $namespaceForm + ); + + $form .= Xml::submitButton( + $this->msg( 'watchlist-submit' )->text(), + [ 'class' => 'cloption-submit' ] + ) . "\n"; foreach ( $hiddenFields as $key => $value ) { $form .= Html::hidden( $key, $value ) . "\n"; } $form .= Xml::closeElement( 'fieldset' ) . "\n"; $form .= Xml::closeElement( 'form' ) . "\n"; - $this->getOutput()->addHTML( $form ); + + // Insert a placeholder for RCFilters + if ( $this->isStructuredFilterUiEnabled() ) { + $rcfilterContainer = Html::element( + 'div', + [ 'class' => 'rcfilters-container' ] + ); + + $loadingContainer = Html::rawElement( + 'div', + [ 'class' => 'rcfilters-spinner' ], + Html::element( + 'div', + [ 'class' => 'rcfilters-spinner-bounce' ] + ) + ); + + // Wrap both with rcfilters-head + $this->getOutput()->addHTML( + Html::rawElement( + 'div', + [ 'class' => 'rcfilters-head' ], + $rcfilterContainer . $form + ) + ); + + // Add spinner + $this->getOutput()->addHTML( $loadingContainer ); + } else { + $this->getOutput()->addHTML( $form ); + } $this->setBottomText( $opts ); } @@ -655,7 +786,7 @@ class SpecialWatchlist extends ChangesListSpecialPage { function setTopText( FormOptions $opts ) { $nondefaults = $opts->getChangedValues(); - $form = ""; + $form = ''; $user = $this->getUser(); $numItems = $this->countItems(); @@ -692,32 +823,27 @@ class SpecialWatchlist extends ChangesListSpecialPage { $form .= Xml::closeElement( 'form' ) . "\n"; } - $form .= Xml::openElement( 'form', [ - 'method' => 'get', - 'action' => wfScript(), - 'id' => 'mw-watchlist-form' - ] ); - $form .= Html::hidden( 'title', $this->getPageTitle()->getPrefixedText() ); - $form .= Xml::fieldset( - $this->msg( 'watchlist-options' )->text(), - false, - [ 'id' => 'mw-watchlist-options' ] - ); - - $form .= $this->makeLegend(); - $this->getOutput()->addHTML( $form ); } - protected function showHideCheck( $options, $message, $name, $value ) { + protected function showHideCheck( $options, $message, $name, $value, $inStructuredUi ) { $options[$name] = 1 - (int)$value; - return '' . Xml::checkLabel( - $this->msg( $message, '' )->text(), - $name, - $name, - (int)$value - ) . ''; + $attribs = [ 'class' => 'mw-input-with-label clshowhideoption cloption' ]; + if ( $inStructuredUi ) { + $attribs[ 'data-feature-in-structured-ui' ] = true; + } + + return Html::rawElement( + 'span', + $attribs, + Xml::checkLabel( + $this->msg( $message, '' )->text(), + $name, + $name, + (int)$value + ) + ); } /**