RCFilters: Hide saved queries from anonymous users
[lhc/web/wiklou.git] / resources / src / mediawiki.rcfilters / mw.rcfilters.Controller.js
index e9981bd..9906119 100644 (file)
@@ -8,11 +8,15 @@
         * @param {mw.rcfilters.dm.FiltersViewModel} filtersModel Filters view model
         * @param {mw.rcfilters.dm.ChangesListViewModel} changesListModel Changes list view model
         * @param {mw.rcfilters.dm.SavedQueriesModel} savedQueriesModel Saved queries model
+        * @param {Object} config Additional configuration
+        * @cfg {string} savedQueriesPreferenceName Where to save the saved queries
         */
-       mw.rcfilters.Controller = function MwRcfiltersController( filtersModel, changesListModel, savedQueriesModel ) {
+       mw.rcfilters.Controller = function MwRcfiltersController( filtersModel, changesListModel, savedQueriesModel, config ) {
                this.filtersModel = filtersModel;
                this.changesListModel = changesListModel;
                this.savedQueriesModel = savedQueriesModel;
+               this.savedQueriesPreferenceName = config.savedQueriesPreferenceName;
+
                this.requestCounter = {};
                this.baseFilterState = {};
                this.uriProcessor = null;
                                        // we should remove all sticky behavior methods completely
                                        // See T172156
                                        // isSticky: true,
+                                       excludedFromSavedQueries: true,
                                        filters: displayConfig.limitArray.map( function ( num ) {
                                                return controller._createFilterDataFromNumber( num, num );
                                        } )
                                        'default': mw.user.options.get( 'rcdays', '30' ),
                                        // Temporarily making this not sticky while limit is not sticky, see above
                                        // isSticky: true,
+                                       excludedFromSavedQueries: true,
                                        filters: [
                                                // Hours (1, 2, 6, 12)
                                                0.04166, 0.0833, 0.25, 0.5
                        this.filtersModel
                );
 
-               try {
-                       parsedSavedQueries = JSON.parse( mw.user.options.get( 'rcfilters-saved-queries' ) || '{}' );
-               } catch ( err ) {
-                       parsedSavedQueries = {};
-               }
+               if ( !mw.user.isAnon() ) {
+                       try {
+                               parsedSavedQueries = JSON.parse( mw.user.options.get( this.savedQueriesPreferenceName ) || '{}' );
+                       } catch ( err ) {
+                               parsedSavedQueries = {};
+                       }
 
-               // The queries are saved in a minimized state, so we need
-               // to send over the base state so the saved queries model
-               // can normalize them per each query item
-               this.savedQueriesModel.initialize(
-                       parsedSavedQueries,
-                       this._getBaseFilterState(),
-                       // This is for backwards compatibility - delete all sticky filter states
-                       Object.keys( this.filtersModel.getStickyFiltersState() )
-               );
+                       // The queries are saved in a minimized state, so we need
+                       // to send over the base state so the saved queries model
+                       // can normalize them per each query item
+                       this.savedQueriesModel.initialize(
+                               parsedSavedQueries,
+                               this._getBaseFilterState(),
+                               // This is for backwards compatibility - delete all excluded filter states
+                               Object.keys( this.filtersModel.getExcludedFiltersState() )
+                       );
+               }
 
                // Check whether we need to load defaults.
                // We do this by checking whether the current URI query
                // or on request
                this.initializing = true;
                if (
-                       this.savedQueriesModel.getDefault() &&
+                       !mw.user.isAnon() && this.savedQueriesModel.getDefault() &&
                        !this.uriProcessor.doesQueryContainRecognizedParams( uri.query )
                ) {
                        // We have defaults from a saved query.
                        // so it gets processed
                        this.changesListModel.update(
                                $changesList.length ? $changesList : 'NO_RESULTS',
-                               $( 'fieldset.rcoptions' ).first(),
+                               $( 'fieldset.cloptions' ).first(),
                                true // We're using existing DOM elements
                        );
                }
                this.filtersModel.toggleInvertedNamespaces();
 
                if (
-                       this.filtersModel.getFiltersByView( 'namespaces' )
-                               .filter( function ( filterItem ) {
-                                       return filterItem.isSelected();
-                               } )
-                               .length
+                       this.filtersModel.getFiltersByView( 'namespaces' ).filter(
+                               function ( filterItem ) { return filterItem.isSelected(); }
+                       ).length
                ) {
                        // Only re-fetch results if there are namespace items that are actually selected
                        this.updateChangesList();
         * @private
         */
        mw.rcfilters.Controller.prototype._shouldCheckForNewChanges = function () {
-               var liveUpdateFeatureFlag = mw.config.get( 'wgStructuredChangeFiltersEnableLiveUpdate' ) ||
-                       new mw.Uri().query.liveupdate;
-
                return !document.hidden &&
                        !this.filtersModel.hasConflict() &&
                        !this.changesListModel.getNewChangesExist() &&
                        !this.updatingChangesList &&
-                       liveUpdateFeatureFlag;
+                       mw.rcfilters.featureFlags.liveUpdate;
        };
 
        /**
                // These are filter states; highlight is stored as boolean
                highlightedItems.highlight = this.filtersModel.isHighlightEnabled();
 
-               // Delete all sticky filters
-               this._deleteStickyValuesFromFilterState( selectedState );
+               // Delete all excluded filters
+               this._deleteExcludedValuesFromFilterState( selectedState );
 
                // Add item
                queryID = this.savedQueriesModel.addNewQuery(
 
                        // Update model state from filters
                        this.filtersModel.toggleFiltersSelected(
-                               // Merge filters with sticky values
-                               $.extend( true, {}, data.filters, this.filtersModel.getStickyFiltersState() )
+                               // Merge filters with excluded values
+                               $.extend( true, {}, data.filters, this.filtersModel.getExcludedFiltersState() )
                        );
 
                        // Update namespace inverted property
                } );
                highlightedItems.highlight = this.filtersModel.isHighlightEnabled();
 
-               // Remove sticky filters
-               this._deleteStickyValuesFromFilterState( selectedState );
+               // Remove anything that should be excluded from the saved query
+               // this includes sticky filters and filters marked with 'excludedFromSavedQueries'
+               this._deleteExcludedValuesFromFilterState( selectedState );
 
                return this.savedQueriesModel.findMatchingQuery(
                        {
         *
         * @param {Object} filterState Filter state
         */
-       mw.rcfilters.Controller.prototype._deleteStickyValuesFromFilterState = function ( filterState ) {
-               // Remove sticky filters
-               $.each( this.filtersModel.getStickyFiltersState(), function ( filterName ) {
+       mw.rcfilters.Controller.prototype._deleteExcludedValuesFromFilterState = function ( filterState ) {
+               // Remove excluded filters
+               $.each( this.filtersModel.getExcludedFiltersState(), function ( filterName ) {
                        delete filterState[ filterName ];
                } );
        };
         * @return {Object} Minimal filters and highlights list
         */
        mw.rcfilters.Controller.prototype._getMinimalFilterList = function ( valuesObject ) {
-               var result = { filters: {}, highlights: {} },
+               var result = { filters: {}, highlights: {}, invert: valuesObject.invert },
                        baseState = this._getBaseFilterState();
 
                // XOR results
                }
 
                // Save the preference
-               new mw.Api().saveOption( 'rcfilters-saved-queries', stringified );
+               new mw.Api().saveOption( this.savedQueriesPreferenceName, stringified );
                // Update the preference for this session
-               mw.user.options.set( 'rcfilters-saved-queries', stringified );
+               mw.user.options.set( this.savedQueriesPreferenceName, stringified );
        };
 
        /**
         * Update the list of changes and notify the model
         *
         * @param {Object} [params] Extra parameters to add to the API call
-        * @param {string} [updateMode='filterChange'] One of 'filterChange', 'liveUpdate', 'showNewChanges'
+        * @param {string} [updateMode='filterChange'] One of 'filterChange', 'liveUpdate', 'showNewChanges', 'markSeen'
         * @return {jQuery.Promise} Promise that is resolved when the update is complete
         */
        mw.rcfilters.Controller.prototype.updateChangesList = function ( params, updateMode ) {
                                                $changesListContent,
                                                $fieldset,
                                                false,
-                                               updateMode === this.SHOW_NEW_CHANGES
+                                               // separator between old and new changes
+                                               updateMode === this.SHOW_NEW_CHANGES || updateMode === this.LIVE_UPDATE
                                        );
                                }.bind( this )
                                // Do nothing for failure
                var data, queryHighlights,
                        savedParams = {},
                        savedHighlights = {},
-                       defaultSavedQueryItem = this.savedQueriesModel.getItemByID( this.savedQueriesModel.getDefault() );
+                       defaultSavedQueryItem = !mw.user.isAnon() && this.savedQueriesModel.getItemByID( this.savedQueriesModel.getDefault() );
 
                if ( defaultSavedQueryItem ) {
                        data = defaultSavedQueryItem.getData();
 
                return $.ajax( uri.toString(), { contentType: 'html' } )
                        .then(
-                               // Success
                                function ( html ) {
-                                       var $parsed;
+                                       var $parsed,
+                                               pieces;
+
                                        if ( !latestRequest() ) {
                                                return $.Deferred().reject();
                                        }
 
                                        $parsed = $( $.parseHTML( html ) );
 
-                                       return {
+                                       pieces = {
                                                // Changes list
                                                changes: $parsed.find( '.mw-changeslist' ).first().contents(),
                                                // Fieldset
-                                               fieldset: $parsed.find( 'fieldset.rcoptions' ).first()
+                                               fieldset: $parsed.find( 'fieldset.cloptions' ).first()
                                        };
+
+                                       // Watchlist returns 200 when there is no results
+                                       if ( pieces.changes.length === 0 ) {
+                                               pieces.changes = 'NO_RESULTS';
+                                       }
+
+                                       return pieces;
                                },
-                               // Failure
+                               // RC returns 404 when there is no results
                                function ( responseObj ) {
                                        var $parsed;
 
                                        // Force a resolve state to this promise
                                        return $.Deferred().resolve( {
                                                changes: 'NO_RESULTS',
-                                               fieldset: $parsed.find( 'fieldset.rcoptions' ).first()
+                                               fieldset: $parsed.find( 'fieldset.cloptions' ).first()
                                        } ).promise();
                                }
                        );
                        this.prevLoggedItems = filters;
                }
        };
+
+       /**
+        * Mark all changes as seen on Watchlist
+        */
+       mw.rcfilters.Controller.prototype.markAllChangesAsSeen = function () {
+               var api = new mw.Api();
+               api.postWithToken( 'csrf', {
+                       formatversion: 2,
+                       action: 'setnotificationtimestamp',
+                       entirewatchlist: true
+               } ).then( function () {
+                       this.updateChangesList( null, 'markSeen' );
+               }.bind( this ) );
+       };
 }( mediaWiki, jQuery ) );