MDL-50783 Ajax: Configure how to call a webservice through db/service.php
[moodle.git] / lib / amd / src / ajax.js
1 // This file is part of Moodle - http://moodle.org/
2 //
3 // Moodle is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, either version 3 of the License, or
6 // (at your option) any later version.
7 //
8 // Moodle is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16 /**
17  * Standard Ajax wrapper for Moodle. It calls the central Ajax script,
18  * which can call any existing webservice using the current session.
19  * In addition, it can batch multiple requests and return multiple responses.
20  *
21  * @module     core/ajax
22  * @class      ajax
23  * @package    core
24  * @copyright  2015 Damyon Wiese <damyon@moodle.com>
25  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26  * @since      2.9
27  */
28 define(['jquery', 'core/config'], function($, config) {
30     /**
31      * Success handler. Called when the ajax call succeeds. Checks each response and
32      * resolves or rejects the deferred from that request.
33      *
34      * @method requestSuccess
35      * @private
36      * @param {Object[]} responses Array of responses containing error, exception and data attributes.
37      */
38     var requestSuccess = function(responses) {
39         // Call each of the success handlers.
40         var requests = this;
41         var exception = null;
42         var i = 0;
43         var request;
44         var response;
46         for (i = 0; i < requests.length; i++) {
47             request = requests[i];
49             response = responses[i];
50             // We may not have responses for all the requests.
51             if (typeof response !== "undefined") {
52                 if (response.error === false) {
53                     // Call the done handler if it was provided.
54                     request.deferred.resolve(response.data);
55                 } else {
56                     exception = response.exception;
57                     break;
58                 }
59             } else {
60                 // This is not an expected case.
61                 exception = new Error('missing response');
62                 break;
63             }
64         }
65         // Something failed, reject the remaining promises.
66         if (exception !== null) {
67             for (; i < requests.length; i++) {
68                 request = requests[i];
69                 request.deferred.reject(exception);
70             }
71         }
72     };
74     /**
75      * Fail handler. Called when the ajax call fails. Rejects all deferreds.
76      *
77      * @method requestFail
78      * @private
79      * @param {jqXHR} jqXHR The ajax object.
80      * @param {string} textStatus The status string.
81      */
82     var requestFail = function(jqXHR, textStatus) {
83         // Reject all the promises.
84         var requests = this;
86         var i = 0;
87         for (i = 0; i < requests.length; i++) {
88             var request = requests[i];
90             if (typeof request.fail != "undefined") {
91                 request.deferred.reject(textStatus);
92             }
93         }
94     };
96     return /** @alias module:core/ajax */ {
97         // Public variables and functions.
98         /**
99          * Make a series of ajax requests and return all the responses.
100          *
101          * @method call
102          * @param {Object[]} Array of requests with each containing methodname and args properties.
103          *                   done and fail callbacks can be set for each element in the array, or the
104          *                   can be attached to the promises returned by this function.
105          * @param {Boolean} async Optional, defaults to true.
106          *                  If false - this function will not return until the promises are resolved.
107          * @param {Boolean} loginrequired Optional, defaults to true.
108          *                  If false - this function will call the faster nologin ajax script - but
109          *                  will fail unless all functions have been marked as 'loginrequired' => false
110          *                  in services.php
111          * @return {Promise[]} Array of promises that will be resolved when the ajax call returns.
112          */
113         call: function(requests, async, loginrequired) {
114             var ajaxRequestData = [],
115                 i,
116                 promises = [];
118             if (typeof async === "undefined") {
119                 async = true;
120             }
121             for (i = 0; i < requests.length; i++) {
122                 var request = requests[i];
123                 ajaxRequestData.push({
124                     index: i,
125                     methodname: request.methodname,
126                     args: request.args
127                 });
128                 request.deferred = $.Deferred();
129                 promises.push(request.deferred.promise());
130                 // Allow setting done and fail handlers as arguments.
131                 // This is just a shortcut for the calling code.
132                 if (typeof request.done !== "undefined") {
133                     request.deferred.done(request.done);
134                 }
135                 if (typeof request.fail !== "undefined") {
136                     request.deferred.fail(request.fail);
137                 }
138                 request.index = i;
139             }
141             ajaxRequestData = JSON.stringify(ajaxRequestData);
142             var settings = {
143                 type: 'POST',
144                 data: ajaxRequestData,
145                 context: requests,
146                 dataType: 'json',
147                 processData: false,
148                 async: async
149             };
151             var script = config.wwwroot + '/lib/ajax/service.php?sesskey=' + config.sesskey;
152             if (!loginrequired) {
153                 script = config.wwwroot + '/lib/ajax/service-nologin.php?sesskey=' + config.sesskey;
154             }
156             // Jquery deprecated done and fail with async=false so we need to do this 2 ways.
157             if (async) {
158                 $.ajax(script, settings)
159                     .done(requestSuccess)
160                     .fail(requestFail);
161             } else {
162                 settings.success = requestSuccess;
163                 settings.error = requestFail;
164                 $.ajax(script, settings);
165             }
167             return promises;
168         }
169     };
170 });