Matthias Mullie has uploaded a new change for review.
https://gerrit.wikimedia.org/r/206826
Change subject: Get rid over queryMap overrides
......................................................................
Get rid over queryMap overrides
This override system was way too complex & passing code around
from method to method for no great reason.
There was only 1 slightly more complex prehandler: watch/unwatch.
That one has a conditional depending on an existing data in
queryMap.
Instead of waiting until the request is about to happen to
generate the queryMap, I'm doing that first. This now allows all
preHandlers to access that data - no more need for the overrides-
callback, or even passing around overrides at all: we can now
just pass the queryMap the preHandlers return.
This is a pre-req for a followup patch where those preHandlers'
returns will be chained into promise handlers, each adding
their own data to the mix. Without this, that was impossible.
Change-Id: Ie117b2f7ca380e88b1998d0d154675a5fcb5d9fa
---
M modules/engine/components/board/base/flow-board-api-events.js
M modules/engine/components/board/features/flow-board-loadmore.js
M modules/engine/components/board/features/flow-board-toc.js
M modules/engine/components/common/flow-component-events.js
M modules/engine/misc/flow-api.js
5 files changed, 83 insertions(+), 122 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Flow
refs/changes/26/206826/1
diff --git a/modules/engine/components/board/base/flow-board-api-events.js
b/modules/engine/components/board/base/flow-board-api-events.js
index e0de540..3a7b272 100644
--- a/modules/engine/components/board/base/flow-board-api-events.js
+++ b/modules/engine/components/board/base/flow-board-api-events.js
@@ -34,9 +34,11 @@
* real editor can be anything, depending on the type of editor)
*
* @param {Event} event
+ * @param {object} info
+ * @param {object} queryMap
* @return {Object}
*/
-
FlowBoardComponentApiEventsMixin.UI.events.globalApiPreHandlers.prepareEditor =
function ( event ) {
+
FlowBoardComponentApiEventsMixin.UI.events.globalApiPreHandlers.prepareEditor =
function ( event, info, queryMap ) {
var $textareas = $( this ).closest( 'form' ).find( 'textarea' ),
override = {};
@@ -59,7 +61,7 @@
// add its own nodes, which may be picked up by
serializeArray()
} );
- return override;
+ return $.extend( queryMap, override );
};
/**
@@ -68,14 +70,16 @@
* This will prepare the data-to-be-submitted so that the override is
* submitted against the most current revision ID.
* @param {Event} event
+ * @param {object} info
+ * @param {object} queryMap
* @return {Object}
*/
-
FlowBoardComponentApiEventsMixin.UI.events.globalApiPreHandlers.prepareEditConflict
= function ( event ) {
+
FlowBoardComponentApiEventsMixin.UI.events.globalApiPreHandlers.prepareEditConflict
= function ( event, info, queryMap ) {
var $form = $( this ).closest( 'form' ),
prevRevisionId = $form.data( 'flow-prev-revision' );
if ( !prevRevisionId ) {
- return {};
+ return queryMap;
}
// Get rid of the temp-saved new revision ID
@@ -87,81 +91,89 @@
* be properly applied for the respective API call; e.g.
* epprev_revision (for edit post)
*/
- return {
+ return $.extend( queryMap, {
flow_prev_revision: prevRevisionId
- };
+ } );
};
/**
* Before activating header, sends an overrideObject to the API to
modify the request params.
* @param {Event} event
+ * @param {object} info
+ * @param {object} queryMap
* @return {Object}
*/
-
FlowBoardComponentApiEventsMixin.UI.events.apiPreHandlers.activateEditHeader =
function () {
- return {
+
FlowBoardComponentApiEventsMixin.UI.events.apiPreHandlers.activateEditHeader =
function ( event, info, queryMap ) {
+ return $.extend( queryMap, {
submodule: 'view-header', // href submodule is
edit-header
vhformat: mw.flow.editor.getFormat() // href does not
have this param
- };
+ } );
};
/**
* Before activating topic, sends an overrideObject to the API to
modify the request params.
*
* @param {Event} event
+ * @param {object} info
+ * @param {object} queryMap
* @return {Object}
*/
-
FlowBoardComponentApiEventsMixin.UI.events.apiPreHandlers.activateEditTitle =
function ( event ) {
+
FlowBoardComponentApiEventsMixin.UI.events.apiPreHandlers.activateEditTitle =
function ( event, info, queryMap ) {
// Use view-post API for topic as well; we only want this on
// particular (title) post revision, not the full topic
- return {
+ return $.extend( queryMap, {
submodule: "view-post",
vppostId: $( this ).closest( '.flow-topic' ).data(
'flow-id' ),
vpformat: mw.flow.editor.getFormat()
- };
+ } );
};
/**
* Before activating post, sends an overrideObject to the API to modify
the request params.
* @param {Event} event
+ * @param {object} info
+ * @param {object} queryMap
* @return {Object}
*/
-
FlowBoardComponentApiEventsMixin.UI.events.apiPreHandlers.activateEditPost =
function ( event ) {
- return {
+
FlowBoardComponentApiEventsMixin.UI.events.apiPreHandlers.activateEditPost =
function ( event, info, queryMap ) {
+ return $.extend( queryMap, {
submodule: 'view-post',
vppostId: $( this ).closest( '.flow-post' ).data(
'flow-id' ),
vpformat: mw.flow.editor.getFormat()
- };
+ } );
};
/**
* Adjusts query params to use global watch action, and specifies it
should use a watch token.
* @param {Event} event
+ * @param {object} info
+ * @param {object} queryMap
* @returns {Function}
*/
- FlowBoardComponentApiEventsMixin.UI.events.apiPreHandlers.watchItem =
function ( event ) {
- return function ( queryMap ) {
- var params = {
- action: 'watch',
- titles: queryMap.page,
- _internal: {
- tokenType: 'watch'
- }
- };
- if ( queryMap.submodule === 'unwatch' ) {
- params.unwatch = 1;
+ FlowBoardComponentApiEventsMixin.UI.events.apiPreHandlers.watchItem =
function ( event, info, queryMap ) {
+ var params = {
+ action: 'watch',
+ titles: queryMap.page,
+ _internal: {
+ tokenType: 'watch'
}
- return params;
};
+ if ( queryMap.submodule === 'unwatch' ) {
+ params.unwatch = 1;
+ }
+
+ return params;
};
/**
* Before activating summarize topic, sends an overrideObject to the
* API to modify the request params.
* @param {Event} event
- * @param {Object} info
+ * @param {object} info
+ * @param {object} queryMap
* @return {Object}
*/
-
FlowBoardComponentApiEventsMixin.UI.events.apiPreHandlers.activateSummarizeTopic
= function ( event, info ) {
+
FlowBoardComponentApiEventsMixin.UI.events.apiPreHandlers.activateSummarizeTopic
= function ( event, info, queryMap ) {
if ( info.$target.find( 'form' ).length ) {
// Form already open; cancel the old form
var flowBoard = mw.flow.getPrototypeMethod( 'board',
'getInstanceByElement' )( $( this ) );
@@ -169,29 +181,31 @@
return false;
}
- return {
+ return $.extend( queryMap, {
// href submodule is edit-topic-summary
submodule: 'view-topic-summary',
// href does not have this param
vtsformat: mw.flow.editor.getFormat()
- };
+ } );
};
/**
* Before activating lock/unlock edit form, sends an overrideObject
* to the API to modify the request params.
* @param {Event} event
+ * @param {object} info
+ * @param {object} queryMap
* @return {Object}
*/
-
FlowBoardComponentApiEventsMixin.UI.events.apiPreHandlers.activateLockTopic =
function ( event ) {
- return {
+
FlowBoardComponentApiEventsMixin.UI.events.apiPreHandlers.activateLockTopic =
function ( event, info, queryMap ) {
+ return $.extend( queryMap, {
// href submodule is lock-topic
submodule: 'view-post',
// href does not have this param
vpformat: 'wikitext',
// request just the data for this topic
vppostId: $( this ).data( 'flow-id' )
- };
+ } );
};
//
diff --git a/modules/engine/components/board/features/flow-board-loadmore.js
b/modules/engine/components/board/features/flow-board-loadmore.js
index c7024a5..c08c0f8 100644
--- a/modules/engine/components/board/features/flow-board-loadmore.js
+++ b/modules/engine/components/board/features/flow-board-loadmore.js
@@ -159,9 +159,10 @@
* @param {Event} event
* @param {Object} info
* @param {jQuery} info.$target
+ * @param {object} queryMap
* @param {FlowBoardComponent} info.component
*/
- function flowBoardComponentLoadMoreFeatureBoardApiPreHandler( event,
info ) {
+ function flowBoardComponentLoadMoreFeatureBoardApiPreHandler( event,
info, queryMap ) {
// Backup the topic data
info.component.renderedTopicsBackup =
info.component.renderedTopics;
info.component.topicTitlesByIdBackup =
info.component.topicTitlesById;
diff --git a/modules/engine/components/board/features/flow-board-toc.js
b/modules/engine/components/board/features/flow-board-toc.js
index 4d64730..d9843c5 100644
--- a/modules/engine/components/board/features/flow-board-toc.js
+++ b/modules/engine/components/board/features/flow-board-toc.js
@@ -38,9 +38,10 @@
* @param {Event} event
* @param {Object} info
* @param {jQuery} info.$target
+ * @param {object} queryMap
* @param {FlowBoardComponent} info.component
*/
- function flowBoardComponentTocFeatureMixinBoardApiPreHandler( event,
info ) {
+ function flowBoardComponentTocFeatureMixinBoardApiPreHandler( event,
info, queryMap ) {
info.component.topicIdsInTocBackup =
info.component.topicIdsInToc;
info.component.lastTopicIdInTocBackup =
info.component.lastTopicIdInToc;
@@ -60,9 +61,10 @@
* @param {Event} event
* @param {Object} info
* @param {jQuery} info.$target
+ * @param {object} queryMap
* @param {FlowBoardComponent} info.component
*/
- function flowBoardComponentTocFeatureMixinTopicListApiPreHandler(
event, info, extraParameters ) {
+ function flowBoardComponentTocFeatureMixinTopicListApiPreHandler(
event, info, queryMap, extraParameters ) {
var $this = $( this ),
isLoadMoreButton = $this.data( 'flow-load-handler' )
=== 'loadMore',
overrides;
@@ -99,7 +101,7 @@
delete overrides.topiclist_sortby;
}
- return overrides;
+ return $.extend( queryMap, overrides );
}
FlowBoardComponentTocFeatureMixin.UI.events.apiPreHandlers.topicList =
flowBoardComponentTocFeatureMixinTopicListApiPreHandler;
diff --git a/modules/engine/components/common/flow-component-events.js
b/modules/engine/components/common/flow-component-events.js
index 8a20709..226fbd4 100644
--- a/modules/engine/components/common/flow-component-events.js
+++ b/modules/engine/components/common/flow-component-events.js
@@ -265,13 +265,13 @@
flowComponent = mw.flow.getPrototypeMethod(
'component', 'getInstanceByElement' )( $this ),
dataParams = $this.data(),
handlerName = dataParams.flowApiHandler,
- preHandlerReturns = [],
info = {
$target: null,
status: null,
component: flowComponent
},
- args = Array.prototype.slice.call( arguments, 0 );
+ args = Array.prototype.slice.call( arguments, 0 ),
+ queryMap = flowComponent.Api.getQueryMap( self.href ||
self );
event.preventDefault();
@@ -285,8 +285,10 @@
$target = $this;
}
+ // insert queryMap & info into args for prehandler
info.$target = $target;
- args.splice( 1, 0, info ); // insert info into args for
prehandler
+ args.splice( 1, 0, info );
+ args.splice( 2, 0, queryMap );
// Make sure an API call is not already in progress for this
target
if ( $target.closest( '.flow-api-inprogress' ).length ) {
@@ -301,7 +303,7 @@
// Let generic pre-handler take care of edit conflicts
$.each( flowComponent.UI.events.globalApiPreHandlers, function(
key, callbackArray ) {
$.each( callbackArray, function ( i, callbackFn ) {
- preHandlerReturns.push( callbackFn.apply( self,
args ) );
+ queryMap = callbackFn.apply( self, args );
} );
} );
@@ -313,15 +315,18 @@
if ( flowComponent.UI.events.apiPreHandlers[ handlerName ] ) {
// apiPreHandlers can return FALSE to prevent
processing,
// nothing at all to proceed,
- // or OBJECT to add param overrides to the API
- // or FUNCTION to modify API params
+ // or new queryMap (= API params)
$.each( flowComponent.UI.events.apiPreHandlers[
handlerName ], function ( i, callbackFn ) {
+ // make sure queryMap is up to date (may have
been altered by
+ // previous preHandler)
+ args.splice( 2, 1, queryMap );
preHandlerReturn = callbackFn.apply( self, args
);
- preHandlerReturns.push( preHandlerReturn );
if ( preHandlerReturn === false ) {
// Callback returned false; break out
of this loop
return false;
+ } else {
+ queryMap = preHandlerReturn;
}
} );
@@ -330,7 +335,7 @@
flowComponent.debug( false, 'apiPreHandler
returned false', handlerName, args );
// Abort any old request in flight; this is
normally done automatically by requestFromNode
- flowComponent.Api.abortOldRequestFromNode(
self, null, null, preHandlerReturns );
+ flowComponent.Api.abortOldRequestFromNode(
self, queryMap, null );
// @todo support for multiple indicators on
same target
$target.removeClass( 'flow-api-inprogress' );
@@ -341,7 +346,7 @@
}
// Make the request
- $deferred = flowComponent.Api.requestFromNode( self,
preHandlerReturns );
+ $deferred = flowComponent.Api.requestFromNode( self, queryMap );
if ( !$deferred ) {
mw.flow.debug( '[FlowApi] [interactiveHandlers]
apiRequest element is not anchor or form element' );
$deferred = $.Deferred();
diff --git a/modules/engine/misc/flow-api.js b/modules/engine/misc/flow-api.js
index d01c6ee..1949950 100644
--- a/modules/engine/misc/flow-api.js
+++ b/modules/engine/misc/flow-api.js
@@ -155,39 +155,12 @@
FlowApi.prototype.setDefaultSubmodule = flowApiSetDefaultSubmodule;
/**
- * Overrides (values of) queryMap with a provided override, which can
come
- * in the form of an object (which the queryMap will be extended with)
or as
- * a function (whose return value will replace queryMap)
- *
- * @param {Object} [queryMap]
- * @param {Function|Object} [override]
- * @returns {Object}
- */
- function flowOverrideQueryMap( queryMap, override ) {
- if ( override ) {
- switch ( typeof override ) {
- // If given an override object, extend our
queryMap with it
- case 'object':
- $.extend( queryMap, override );
- break;
- // If given an override function, call it and
make it return the new queryMap
- case 'function':
- queryMap = override( queryMap );
- break;
- }
- }
-
- return queryMap;
- }
-
- /**
* With a url (a://b.c/d?e=f&g#h) will return an object of key-value
pairs ({e:'f', g:''}).
* @param {String|Element} url
* @param {Object} [queryMap]
- * @param {Array<(Function|Object)>} [overrides]
* @returns {Object}
*/
- function flowApiGetQueryMap( url, queryMap, overrides ) {
+ function flowApiGetQueryMap( url, queryMap ) {
var uri,
queryKey,
queryValue,
@@ -195,7 +168,6 @@
$node, $form, formData;
queryMap = queryMap || {};
- overrides = overrides || [];
// If URL is an Element...
if ( typeof url !== 'string' ) {
@@ -261,11 +233,6 @@
// Default action is flow
queryMap.action = queryMap.action || 'flow';
- // Override the automatically generated queryMap
- for ( i = 0; i < overrides.length; i++ ) {
- queryMap = flowOverrideQueryMap( queryMap, overrides[i]
);
- }
-
// Use the API map to transform this data if necessary, eg.
queryMap = flowApiTransformMap( queryMap );
@@ -278,24 +245,13 @@
* Using a given form, parses its action, serializes the data, and
sends it as GET or POST depending on form method.
* With button, its name=value is serialized in. If button is an Event,
it will attempt to find the clicked button.
* Additional params can be set with data-flow-api-params on both the
clicked button or the form.
- * @param {Event|Element} [button]
- * @param {Array<(Function|Object)>} [overrides]
+ * @param {Event|Element} button
+ * @param {Object} queryMap
* @return {$.Deferred}
*/
- function flowApiRequestFromForm( button, overrides ) {
- var $deferred = $.Deferred(),
- $button = $( button ),
- method = $button.closest( 'form' ).attr( 'method' ) ||
'GET',
- queryMap;
-
- // Parse the form action to get the rest of the queryMap
- if ( !( queryMap = this.getQueryMap( button, null, overrides )
) ) {
- return $deferred.rejectWith( { error: 'Invalid form
action' } );
- }
-
- if ( !( queryMap.action ) ) {
- return $deferred.rejectWith( { error: 'Unknown action
for form' } );
- }
+ function flowApiRequestFromForm( button, queryMap ) {
+ var $button = $( button ),
+ method = $button.closest( 'form' ).attr( 'method' ) ||
'GET';
// Cancel any old form request, and also trigger a new one
return this.abortOldRequestFromNode( $button, queryMap, method
);
@@ -307,20 +263,12 @@
* Using a given anchor, parses its URL and sends it as a GET (default)
or POST depending on data-flow-api-method.
* Additional params can be set with data-flow-api-params.
* @param {Element} anchor
- * @param {Array<(Function|Object)>} [overrides]
+ * @param {Object} queryMap
* @return {$.Deferred}
*/
- function flowApiRequestFromAnchor( anchor, overrides ) {
+ function flowApiRequestFromAnchor( anchor, queryMap ) {
var $anchor = $( anchor ),
- $deferred = $.Deferred(),
- queryMap,
method = $anchor.data( 'flow-api-method' ) || 'GET';
-
- // Build the query map from this anchor's HREF
- if ( !( queryMap = this.getQueryMap( anchor.href, null,
overrides ) ) ) {
- mw.flow.debug( '[FlowApi] requestFromAnchor error:
invalid href', arguments );
- return $deferred.rejectWith( { error: 'Invalid href' }
);
- }
// Abort any old requests, and have it issue a new one via GET
or POST
return this.abortOldRequestFromNode( $anchor, queryMap, method
);
@@ -331,10 +279,10 @@
/**
* Automatically calls requestFromAnchor or requestFromForm depending
on the type of node given.
* @param {Element} node
- * @param {Array<(Function|Object)>} [overrides]
- * @return {$.Deferred|bool}
+ * @param {Object} queryMap
+ * @return {$.Deferred}
*/
- function flowApiRequestFromNode( node, overrides ) {
+ function flowApiRequestFromNode( node, queryMap ) {
var $node = $( node );
if ( $node.is( 'a' ) ) {
@@ -342,7 +290,7 @@
} else if ( $node.is( 'form, input, button, textarea, select,
option' ) ) {
return this.requestFromForm.apply( this, arguments );
} else {
- return false;
+ return $.Deferred().reject();
}
}
@@ -352,21 +300,12 @@
* Handles aborting an old in-flight API request.
* If startNewMethod is given, this method also STARTS a new API call
and stores it for later abortion if needed.
* @param {jQuery|Element} $node
- * @param {Object} [queryMap]
+ * @param {Object} queryMap
* @param {String} [startNewMethod] If given: starts, stores, and
returns a new API call
- * @param {Array<(Function|Object)>} [overrides]
* @return {undefined|$.Deferred}
*/
- function flowApiAbortOldRequestFromNode( $node, queryMap,
startNewMethod, overrides ) {
+ function flowApiAbortOldRequestFromNode( $node, queryMap,
startNewMethod ) {
$node = $( $node );
-
- if ( !queryMap ) {
- // Get the queryMap automatically if one wasn't given
- if ( !( queryMap = this.getQueryMap( $node, null,
overrides ) ) ) {
- mw.flow.debug( '[FlowApi]
abortOldRequestFromNode failed to find a queryMap', arguments );
- return;
- }
- }
// If this anchor already has a request in flight, abort it
var str = 'flow-api-query-temp-' + queryMap.action + '-' +
queryMap.submodule,
--
To view, visit https://gerrit.wikimedia.org/r/206826
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ie117b2f7ca380e88b1998d0d154675a5fcb5d9fa
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Flow
Gerrit-Branch: master
Gerrit-Owner: Matthias Mullie <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits