X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/6746dc89c47ed01b165cc1152533605f97eb8e8d..f562e4c6e5fac7bcb445985b99acbea4d706e6f0:/src/data/proxy/Server.js diff --git a/src/data/proxy/Server.js b/src/data/proxy/Server.js index 4f984395..4f8e0f4c 100644 --- a/src/data/proxy/Server.js +++ b/src/data/proxy/Server.js @@ -14,134 +14,132 @@ If you are unsure which license is appropriate for your use, please contact the */ /** * @author Ed Spencer - * @class Ext.data.proxy.Server - * @extends Ext.data.proxy.Proxy - * - *

ServerProxy is a superclass of {@link Ext.data.proxy.JsonP JsonPProxy} and {@link Ext.data.proxy.Ajax AjaxProxy}, - * and would not usually be used directly.

- * - *

ServerProxy should ideally be named HttpProxy as it is a superclass for all HTTP proxies - for Ext JS 4.x it has been - * called ServerProxy to enable any 3.x applications that reference the HttpProxy to continue to work (HttpProxy is now an - * alias of AjaxProxy).

+ * + * ServerProxy is a superclass of {@link Ext.data.proxy.JsonP JsonPProxy} and {@link Ext.data.proxy.Ajax AjaxProxy}, and + * would not usually be used directly. + * + * ServerProxy should ideally be named HttpProxy as it is a superclass for all HTTP proxies - for Ext JS 4.x it has been + * called ServerProxy to enable any 3.x applications that reference the HttpProxy to continue to work (HttpProxy is now + * an alias of AjaxProxy). + * @private */ Ext.define('Ext.data.proxy.Server', { extend: 'Ext.data.proxy.Proxy', alias : 'proxy.server', alternateClassName: 'Ext.data.ServerProxy', uses : ['Ext.data.Request'], - - /** - * @cfg {String} url The URL from which to request the data object. - */ - - /** - * @cfg {Object/String/Ext.data.reader.Reader} reader The Ext.data.reader.Reader to use to decode the server's response. This can - * either be a Reader instance, a config object or just a valid Reader type name (e.g. 'json', 'xml'). - */ - + /** - * @cfg {Object/String/Ext.data.writer.Writer} writer The Ext.data.writer.Writer to use to encode any request sent to the server. - * This can either be a Writer instance, a config object or just a valid Writer type name (e.g. 'json', 'xml'). + * @cfg {String} url + * The URL from which to request the data object. */ - + /** - * @cfg {String} pageParam The name of the 'page' parameter to send in a request. Defaults to 'page'. Set this to - * undefined if you don't want to send a page parameter + * @cfg {String} pageParam + * The name of the 'page' parameter to send in a request. Defaults to 'page'. Set this to undefined if you don't + * want to send a page parameter. */ pageParam: 'page', - + /** - * @cfg {String} startParam The name of the 'start' parameter to send in a request. Defaults to 'start'. Set this - * to undefined if you don't want to send a start parameter + * @cfg {String} startParam + * The name of the 'start' parameter to send in a request. Defaults to 'start'. Set this to undefined if you don't + * want to send a start parameter. */ startParam: 'start', /** - * @cfg {String} limitParam The name of the 'limit' parameter to send in a request. Defaults to 'limit'. Set this - * to undefined if you don't want to send a limit parameter + * @cfg {String} limitParam + * The name of the 'limit' parameter to send in a request. Defaults to 'limit'. Set this to undefined if you don't + * want to send a limit parameter. */ limitParam: 'limit', - + /** - * @cfg {String} groupParam The name of the 'group' parameter to send in a request. Defaults to 'group'. Set this - * to undefined if you don't want to send a group parameter + * @cfg {String} groupParam + * The name of the 'group' parameter to send in a request. Defaults to 'group'. Set this to undefined if you don't + * want to send a group parameter. */ groupParam: 'group', - + /** - * @cfg {String} sortParam The name of the 'sort' parameter to send in a request. Defaults to 'sort'. Set this - * to undefined if you don't want to send a sort parameter + * @cfg {String} sortParam + * The name of the 'sort' parameter to send in a request. Defaults to 'sort'. Set this to undefined if you don't + * want to send a sort parameter. */ sortParam: 'sort', - + /** - * @cfg {String} filterParam The name of the 'filter' parameter to send in a request. Defaults to 'filter'. Set - * this to undefined if you don't want to send a filter parameter + * @cfg {String} filterParam + * The name of the 'filter' parameter to send in a request. Defaults to 'filter'. Set this to undefined if you don't + * want to send a filter parameter. */ filterParam: 'filter', - + /** - * @cfg {String} directionParam The name of the direction parameter to send in a request. This is only used when simpleSortMode is set to true. - * Defaults to 'dir'. + * @cfg {String} directionParam + * The name of the direction parameter to send in a request. **This is only used when simpleSortMode is set to + * true.** Defaults to 'dir'. */ directionParam: 'dir', - + /** - * @cfg {Boolean} simpleSortMode Enabling simpleSortMode in conjunction with remoteSort will only send one sort property and a direction when a remote sort is requested. - * The directionParam and sortParam will be sent with the property name and either 'ASC' or 'DESC' + * @cfg {Boolean} simpleSortMode + * Enabling simpleSortMode in conjunction with remoteSort will only send one sort property and a direction when a + * remote sort is requested. The directionParam and sortParam will be sent with the property name and either 'ASC' + * or 'DESC'. */ simpleSortMode: false, - + /** - * @cfg {Boolean} noCache (optional) Defaults to true. Disable caching by adding a unique parameter - * name to the request. + * @cfg {Boolean} noCache + * Disable caching by adding a unique parameter name to the request. Set to false to allow caching. Defaults to true. */ noCache : true, - + /** - * @cfg {String} cacheString The name of the cache param added to the url when using noCache (defaults to "_dc") + * @cfg {String} cacheString + * The name of the cache param added to the url when using noCache. Defaults to "_dc". */ cacheString: "_dc", - + /** - * @cfg {Number} timeout (optional) The number of milliseconds to wait for a response. - * Defaults to 30000 milliseconds (30 seconds). + * @cfg {Number} timeout + * The number of milliseconds to wait for a response. Defaults to 30000 milliseconds (30 seconds). */ timeout : 30000, - + /** * @cfg {Object} api - * Specific urls to call on CRUD action methods "create", "read", "update" and "destroy". - * Defaults to:

-api: {
-    create  : undefined,
-    read    : undefined,
-    update  : undefined,
-    destroy : undefined
-}
-     * 
- *

The url is built based upon the action being executed [create|read|update|destroy] - * using the commensurate {@link #api} property, or if undefined default to the - * configured {@link Ext.data.Store}.{@link Ext.data.proxy.Server#url url}.


- *

For example:

- *

-api: {
-    create  : '/controller/new',
-    read    : '/controller/load',
-    update  : '/controller/update',
-    destroy : '/controller/destroy_action'
-}
-     * 
- *

If the specific URL for a given CRUD action is undefined, the CRUD action request - * will be directed to the configured {@link Ext.data.proxy.Server#url url}.

- */ - - /** - * @ignore + * Specific urls to call on CRUD action methods "create", "read", "update" and "destroy". Defaults to: + * + * api: { + * create : undefined, + * read : undefined, + * update : undefined, + * destroy : undefined + * } + * + * The url is built based upon the action being executed [create|read|update|destroy] using the commensurate + * {@link #api} property, or if undefined default to the configured + * {@link Ext.data.Store}.{@link Ext.data.proxy.Server#url url}. + * + * For example: + * + * api: { + * create : '/controller/new', + * read : '/controller/load', + * update : '/controller/update', + * destroy : '/controller/destroy_action' + * } + * + * If the specific URL for a given CRUD action is undefined, the CRUD action request will be directed to the + * configured {@link Ext.data.proxy.Server#url url}. */ + constructor: function(config) { var me = this; - + config = config || {}; this.addEvents( /** @@ -154,36 +152,37 @@ api: { 'exception' ); me.callParent([config]); - + /** - * @cfg {Object} extraParams Extra parameters that will be included on every request. Individual requests with params - * of the same name will override these params when they are in conflict. + * @cfg {Object} extraParams + * Extra parameters that will be included on every request. Individual requests with params of the same name + * will override these params when they are in conflict. */ me.extraParams = config.extraParams || {}; - + me.api = config.api || {}; - + //backwards compatibility, will be deprecated in 5.0 me.nocache = me.noCache; }, - + //in a ServerProxy all four CRUD operations are executed in the same manner, so we delegate to doRequest in each case create: function() { return this.doRequest.apply(this, arguments); }, - + read: function() { return this.doRequest.apply(this, arguments); }, - + update: function() { return this.doRequest.apply(this, arguments); }, - + destroy: function() { return this.doRequest.apply(this, arguments); }, - + /** * Creates and returns an Ext.data.Request object based on the options passed by the {@link Ext.data.Store Store} * that this Proxy is attached to. @@ -193,14 +192,14 @@ api: { buildRequest: function(operation) { var params = Ext.applyIf(operation.params || {}, this.extraParams || {}), request; - + //copy any sorters, filters etc into the params so they can be sent over the wire - params = Ext.applyIf(params, this.getParams(params, operation)); - + params = Ext.applyIf(params, this.getParams(operation)); + if (operation.id && !params.id) { params.id = operation.id; } - + request = Ext.create('Ext.data.Request', { params : params, action : operation.action, @@ -208,56 +207,36 @@ api: { operation: operation, url : operation.url }); - + request.url = this.buildUrl(request); - + /* * Save the request on the Operation. Operations don't usually care about Request and Response data, but in the * ServerProxy and any of its subclasses we add both request and response as they may be useful for further processing */ operation.request = request; - + return request; }, - - /** - * - */ + + // Should this be documented as protected method? processResponse: function(success, operation, request, response, callback, scope){ var me = this, reader, - result, - records, - length, - mc, - record, - i; - + result; + if (success === true) { reader = me.getReader(); result = reader.read(me.extractResponseData(response)); - records = result.records; - length = records.length; - + if (result.success !== false) { - mc = Ext.create('Ext.util.MixedCollection', true, function(r) {return r.getId();}); - mc.addAll(operation.records); - for (i = 0; i < length; i++) { - record = mc.get(records[i].getId()); - - if (record) { - record.beginEdit(); - record.set(record.data); - record.endEdit(true); - } - } - //see comment in buildRequest for why we include the response object here Ext.apply(operation, { response: response, resultSet: result }); - + + operation.commitRecords(result.records); operation.setCompleted(); operation.setSuccessful(); } else { @@ -266,17 +245,17 @@ api: { } } else { me.setException(operation, response); - me.fireEvent('exception', this, response, operation); + me.fireEvent('exception', this, response, operation); } - + //this callback is the one that was passed to the 'read' or 'write' function above if (typeof callback == 'function') { callback.call(scope || me, operation); } - + me.afterRequest(request, success); }, - + /** * Sets up an exception on the operation * @private @@ -287,40 +266,41 @@ api: { operation.setException({ status: response.status, statusText: response.statusText - }); + }); }, - + /** * Template method to allow subclasses to specify how to get the response for the reader. + * @template * @private * @param {Object} response The server response - * @return {Mixed} The response data to be used by the reader + * @return {Object} The response data to be used by the reader */ extractResponseData: function(response){ - return response; + return response; }, - + /** * Encode any values being sent to the server. Can be overridden in subclasses. * @private * @param {Array} An array of sorters/filters. - * @return {Mixed} The encoded value + * @return {Object} The encoded value */ applyEncoding: function(value){ return Ext.encode(value); }, - + /** - * Encodes the array of {@link Ext.util.Sorter} objects into a string to be sent in the request url. By default, + * Encodes the array of {@link Ext.util.Sorter} objects into a string to be sent in the request url. By default, * this simply JSON-encodes the sorter data - * @param {Array} sorters The array of {@link Ext.util.Sorter Sorter} objects + * @param {Ext.util.Sorter[]} sorters The array of {@link Ext.util.Sorter Sorter} objects * @return {String} The encoded sorters */ encodeSorters: function(sorters) { var min = [], length = sorters.length, i = 0; - + for (; i < length; i++) { min[i] = { property : sorters[i].property, @@ -328,20 +308,20 @@ api: { }; } return this.applyEncoding(min); - + }, - + /** - * Encodes the array of {@link Ext.util.Filter} objects into a string to be sent in the request url. By default, + * Encodes the array of {@link Ext.util.Filter} objects into a string to be sent in the request url. By default, * this simply JSON-encodes the filter data - * @param {Array} sorters The array of {@link Ext.util.Filter Filter} objects + * @param {Ext.util.Filter[]} filters The array of {@link Ext.util.Filter Filter} objects * @return {String} The encoded filters */ encodeFilters: function(filters) { var min = [], length = filters.length, i = 0; - + for (; i < length; i++) { min[i] = { property: filters[i].property, @@ -350,15 +330,14 @@ api: { } return this.applyEncoding(min); }, - + /** * @private * Copy any sorters, filters etc into the params so they can be sent over the wire */ - getParams: function(params, operation) { - params = params || {}; - + getParams: function(operation) { var me = this, + params = {}, isDef = Ext.isDefined, groupers = operation.groupers, sorters = operation.sorters, @@ -366,34 +345,34 @@ api: { page = operation.page, start = operation.start, limit = operation.limit, - + simpleSortMode = me.simpleSortMode, - + pageParam = me.pageParam, startParam = me.startParam, limitParam = me.limitParam, groupParam = me.groupParam, sortParam = me.sortParam, filterParam = me.filterParam, - directionParam = me.directionParam; - + directionParam = me.directionParam; + if (pageParam && isDef(page)) { params[pageParam] = page; } - + if (startParam && isDef(start)) { params[startParam] = start; } - + if (limitParam && isDef(limit)) { params[limitParam] = limit; } - + if (groupParam && groupers && groupers.length > 0) { // Grouper is a subclass of sorter, so we can just use the sorter method params[groupParam] = me.encodeSorters(groupers); } - + if (sortParam && sorters && sorters.length > 0) { if (simpleSortMode) { params[sortParam] = sorters[0].property; @@ -401,40 +380,39 @@ api: { } else { params[sortParam] = me.encodeSorters(sorters); } - + } - + if (filterParam && filters && filters.length > 0) { params[filterParam] = me.encodeFilters(filters); } - + return params; }, - + /** - * Generates a url based on a given Ext.data.Request object. By default, ServerProxy's buildUrl will - * add the cache-buster param to the end of the url. Subclasses may need to perform additional modifications - * to the url. + * Generates a url based on a given Ext.data.Request object. By default, ServerProxy's buildUrl will add the + * cache-buster param to the end of the url. Subclasses may need to perform additional modifications to the url. * @param {Ext.data.Request} request The request object * @return {String} The url */ buildUrl: function(request) { var me = this, url = me.getUrl(request); - + // if (!url) { Ext.Error.raise("You are using a ServerProxy but have not supplied it with a url."); } // - + if (me.noCache) { url = Ext.urlAppend(url, Ext.String.format("{0}={1}", me.cacheString, Ext.Date.now())); } - + return url; }, - + /** * Get the url for the request taking into account the order of priority, * - The request @@ -447,11 +425,13 @@ api: { getUrl: function(request){ return request.url || this.api[request.action] || this.url; }, - + /** - * In ServerProxy subclasses, the {@link #create}, {@link #read}, {@link #update} and {@link #destroy} methods all pass - * through to doRequest. Each ServerProxy subclass must implement the doRequest method - see {@link Ext.data.proxy.JsonP} - * and {@link Ext.data.proxy.Ajax} for examples. This method carries the same signature as each of the methods that delegate to it. + * In ServerProxy subclasses, the {@link #create}, {@link #read}, {@link #update} and {@link #destroy} methods all + * pass through to doRequest. Each ServerProxy subclass must implement the doRequest method - see {@link + * Ext.data.proxy.JsonP} and {@link Ext.data.proxy.Ajax} for examples. This method carries the same signature as + * each of the methods that delegate to it. + * * @param {Ext.data.Operation} operation The Ext.data.Operation object * @param {Function} callback The callback function to call when the Operation has completed * @param {Object} scope The scope in which to execute the callback @@ -461,7 +441,7 @@ api: { Ext.Error.raise("The doRequest function has not been implemented on your Ext.data.proxy.Server subclass. See src/data/ServerProxy.js for details"); // }, - + /** * Optional callback function which can be used to clean up after a request has been completed. * @param {Ext.data.Request} request The Request object @@ -469,7 +449,7 @@ api: { * @method */ afterRequest: Ext.emptyFn, - + onDestroy: function() { Ext.destroy(this.reader, this.writer); }