/** * @private * Small utility class used internally to represent a Direct method. */Ext.define('Ext.direct.RemotingMethod', { constructor: function(config) { var me = this, params = config.params, len = config.len, metadataCfg = config.metadata, metadata = {}, name, pLen, p, param; me.name = config.name; me.disableBatching = config.batched != null ? !config.batched : false; if (config.formHandler) { me.formHandler = config.formHandler; } else if (Ext.isNumeric(len)) { // given only the number of parameters me.len = len; me.ordered = true; } else { /* * Given an array of either * a) String * b) Objects with a name property. We may want to encode extra info in here later * c) Empty array signifies no mandatory parameters */ me.named = true; me.strict = config.strict !== undefined ? config.strict : true; me.params = {}; // params may not be defined for a formHandler, or named method // with no strict checking pLen = params && params.length; for (p = 0; p < pLen; p++) { param = params[p]; name = Ext.isObject(param) ? param.name : param; me.params[name] = true; } } if (metadataCfg) { params = metadataCfg.params; len = metadataCfg.len; if (Ext.isNumeric(len)) { //<debug> if (len === 0) { Ext.raise('metadata.len cannot be 0 ' + 'for Ext Direct method ' + me.name); } //</debug> metadata.ordered = true; metadata.len = len; } else if (Ext.isArray(params)) { metadata.named = true; metadata.params = {}; for (p = 0, pLen = params.length; p < pLen; p++) { param = params[p]; metadata.params[param] = true; } metadata.strict = metadataCfg.strict !== undefined ? metadataCfg.strict : true; } //<debug> else { Ext.raise('metadata is neither named nor ordered ' + 'for Ext Direct method ' + me.name); } //</debug> me.metadata = metadata; } }, /** * Prepare Direct function arguments that can be used with getCallData(). */ getArgs: function(config) { var me = this, params = config.params, paramOrder = config.paramOrder, metadata = config.metadata, options = config.options, args = [], flatten, i, len; if (me.ordered) { if (me.len > 0) { // If a paramOrder was specified, add the params into the argument list // in that order. if (paramOrder) { // Direct proxy uses this configuration for its CRUD operations. // We only do this kind of thing for ordered Methods that accept 1 argument, // if there's more or less we fall back to default processing. flatten = config.paramsAsArray && me.len === 1 && (paramOrder.length > 1 || Ext.isArray(params)); if (flatten) { if (Ext.isArray(params)) { for (i = 0, len = params.length; i < len; i++) { args.push(me.convertParams(params[i], paramOrder, paramOrder.length, true)); } } else { args = me.convertParams(params, paramOrder, paramOrder.length, true); } if (!params.allowSingle || args.length > 1) { args = [args]; } } else { // The number of arguments expected by the Method has priority // over the number of parameters in paramOrder. args = me.convertParams(params, paramOrder, me.len, false); } } else { args.push(params); } } } else { args.push(params); } args.push(config.callback, config.scope || window); if (options || metadata) { options = Ext.apply({}, options); if (metadata) { // Could be either an object of named arguments, // or an array of ordered arguments options.metadata = metadata; } args.push(options); } return args; }, convertParams: function(params, paramOrder, count, flatten) { var ret = [], paramName, i, len; for (i = 0, len = count; i < len; i++) { paramName = paramOrder[i]; ret.push(params[paramName]); } if (flatten) { return ret.length === 0 ? undefined : ret.length === 1 ? ret[0] : ret; } else { return ret; } }, /** * Takes the arguments for a Direct function and splits the arguments * from the scope and the callback. * * @param {Array} args The arguments passed to the direct call * * @return {Object} An object with 4 properties: args, callback, scope, and options object. */ getCallData: function(args) { var me = this, data = null, len = me.len, params = me.params, strict = me.strict, form, callback, scope, name, options, metadata; // Historically, the presence of required arguments was not checked; // another idiosyncrasy is that null is sent to the server side // instead of empty array when len === 0 if (me.ordered) { callback = args[len]; scope = args[len + 1]; options = args[len + 2]; if (len !== 0) { data = args.slice(0, len); } } else if (me.formHandler) { form = args[0]; callback = args[1]; scope = args[2]; options = args[3]; } else { data = Ext.apply({}, args[0]); callback = args[1]; scope = args[2]; options = args[3]; // filter out any non-existent properties unless !strict if (strict) { for (name in data) { if (data.hasOwnProperty(name) && !params[name]) { delete data[name]; } } } } if (me.metadata && options && options.metadata) { if (me.metadata.ordered) { //<debug> if (!Ext.isArray(options.metadata)) { Ext.raise('options.metadata is not an Array ' + 'for Ext Direct method ' + me.name); } else if (options.metadata.length < me.metadata.len) { Ext.raise('Not enough parameters in options.metadata ' + 'for Ext Direct method ' + me.name); } //</debug> metadata = options.metadata.slice(0, me.metadata.len); } else { //<debug> if (!Ext.isObject(options.metadata)) { Ext.raise('options.metadata is not an Object ' + 'for Ext Direct method ' + me.name); } //</debug> metadata = Ext.apply({}, options.metadata); if (me.metadata.strict) { for (name in metadata) { if (metadata.hasOwnProperty(name) && !me.metadata.params[name]) { delete metadata[name]; } } } //<debug> for (name in me.metadata.params) { if (!metadata.hasOwnProperty(name)) { Ext.raise('Named parameter ' + name + ' is missing ' + 'in options.metadata for Ext Direct method ' + me.name); } } //</debug> } delete options.metadata; } return { form: form, data: data, metadata: metadata, callback: callback, scope: scope, options: options }; }});