// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
/**
* Standard Ajax wrapper for Moodle. It calls the central Ajax script,
* which can call any existing webservice using the current session.
* In addition, it can batch multiple requests and return multiple responses.
*
* @module core/ajax
* @class ajax
* @package core
* @copyright 2015 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 2.9
*/
define(['jquery', 'core/config'], function($, config) {
/**
* Success handler. Called when the ajax call succeeds. Checks each response and
* resolves or rejects the deferred from that request.
*
* @method requestSuccess
* @private
* @param {Object[]} responses Array of responses containing error, exception and data attributes.
*/
var requestSuccess = function(responses) {
// Call each of the success handlers.
var requests = this;
var exception = null;
var i = 0;
var request;
var response;
for (i = 0; i < requests.length; i++) {
request = requests[i];
response = responses[i];
// We may not have responses for all the requests.
if (typeof response !== "undefined") {
if (response.error === false) {
// Call the done handler if it was provided.
request.deferred.resolve(response.data);
} else {
exception = response.exception;
break;
}
} else {
// This is not an expected case.
exception = new Error('missing response');
break;
}
}
// Something failed, reject the remaining promises.
if (exception !== null) {
for (; i < requests.length; i++) {
request = requests[i];
request.deferred.reject(exception);
}
}
};
/**
* Fail handler. Called when the ajax call fails. Rejects all deferreds.
*
* @method requestFail
* @private
* @param {jqXHR} jqXHR The ajax object.
* @param {string} textStatus The status string.
*/
var requestFail = function(jqXHR, textStatus) {
// Reject all the promises.
var requests = this;
var i = 0;
for (i = 0; i < requests.length; i++) {
var request = requests[i];
if (typeof request.fail != "undefined") {
request.deferred.reject(textStatus);
}
}
};
return /** @alias module:core/ajax */ {
// Public variables and functions.
/**
* Make a series of ajax requests and return all the responses.
*
* @method call
* @param {Object[]} requests Array of requests with each containing methodname and args properties.
* done and fail callbacks can be set for each element in the array, or the
* can be attached to the promises returned by this function.
* @param {Boolean} async Optional, defaults to true.
* If false - this function will not return until the promises are resolved.
* @param {Boolean} loginrequired Optional, defaults to true.
* If false - this function will call the faster nologin ajax script - but
* will fail unless all functions have been marked as 'loginrequired' => false
* in services.php
* @return {Promise[]} Array of promises that will be resolved when the ajax call returns.
*/
call: function(requests, async, loginrequired) {
var ajaxRequestData = [],
i,
promises = [];
if (typeof loginrequired === "undefined") {
loginrequired = true;
}
if (typeof async === "undefined") {
async = true;
}
for (i = 0; i < requests.length; i++) {
var request = requests[i];
ajaxRequestData.push({
index: i,
methodname: request.methodname,
args: request.args
});
request.deferred = $.Deferred();
promises.push(request.deferred.promise());
// Allow setting done and fail handlers as arguments.
// This is just a shortcut for the calling code.
if (typeof request.done !== "undefined") {
request.deferred.done(request.done);
}
if (typeof request.fail !== "undefined") {
request.deferred.fail(request.fail);
}
request.index = i;
}
ajaxRequestData = JSON.stringify(ajaxRequestData);
var settings = {
type: 'POST',
data: ajaxRequestData,
context: requests,
dataType: 'json',
processData: false,
async: async,
contentType: "application/json"
};
var script = config.wwwroot + '/lib/ajax/service.php?sesskey=' + config.sesskey;
if (!loginrequired) {
script = config.wwwroot + '/lib/ajax/service-nologin.php?sesskey=' + config.sesskey;
}
// Jquery deprecated done and fail with async=false so we need to do this 2 ways.
if (async) {
$.ajax(script, settings)
.done(requestSuccess)
.fail(requestFail);
} else {
settings.success = requestSuccess;
settings.error = requestFail;
$.ajax(script, settings);
}
return promises;
}
};
});