Merge branch 'MDL-49163-master' of git://github.com/damyon/moodle

This commit is contained in:
Dan Poltawski 2015-03-16 11:01:18 +00:00
commit e4d0db1769
9 changed files with 305 additions and 0 deletions

View File

@ -40,6 +40,7 @@ $string['apiexplorer'] = 'API explorer';
$string['apiexplorernotavalaible'] = 'API explorer not available yet.'; $string['apiexplorernotavalaible'] = 'API explorer not available yet.';
$string['arguments'] = 'Arguments'; $string['arguments'] = 'Arguments';
$string['authmethod'] = 'Authentication method'; $string['authmethod'] = 'Authentication method';
$string['callablefromajax'] = 'Callable from AJAX';
$string['cannotcreatetoken'] = 'No permission to create web service token for the service {$a}.'; $string['cannotcreatetoken'] = 'No permission to create web service token for the service {$a}.';
$string['cannotgetcoursecontents'] = 'Cannot get course contents'; $string['cannotgetcoursecontents'] = 'Cannot get course contents';
$string['configwebserviceplugins'] = 'For security reasons, only protocols that are in use should be enabled.'; $string['configwebserviceplugins'] = 'For security reasons, only protocols that are in use should be enabled.';

89
lib/ajax/service.php Normal file
View File

@ -0,0 +1,89 @@
<?php
// 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 <http://www.gnu.org/licenses/>.
/**
* This file is used to call any registered externallib function in Moodle.
*
* It will process more than one request and return more than one response if required.
* It is recommended to add webservice functions and re-use this script instead of
* writing any new custom ajax scripts.
*
* @since Moodle 2.9
* @package core
* @copyright 2015 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define('AJAX_SCRIPT', true);
require_once(dirname(__FILE__) . '/../../config.php');
require_once($CFG->libdir . '/externallib.php');
require_login(null, true, null, true, true);
$rawjson = file_get_contents('php://input');
$requests = json_decode($rawjson, true);
if ($requests === null) {
$lasterror = json_last_error_msg();
throw new coding_exception('Invalid json in request: ' . $lasterror);
}
$responses = array();
foreach ($requests as $request) {
$response = array();
$methodname = clean_param($request['methodname'], PARAM_ALPHANUMEXT);
$index = clean_param($request['index'], PARAM_INT);
$args = $request['args'];
try {
$externalfunctioninfo = external_function_info($methodname);
if (!$externalfunctioninfo->allowed_from_ajax) {
throw new moodle_exception('servicenotavailable', 'webservice');
}
// Validate params, this also sorts the params properly, we need the correct order in the next part.
$callable = array($externalfunctioninfo->classname, 'validate_parameters');
$params = call_user_func($callable,
$externalfunctioninfo->parameters_desc,
$args);
// Execute - gulp!
$callable = array($externalfunctioninfo->classname, $externalfunctioninfo->methodname);
$result = call_user_func_array($callable,
array_values($params));
$response['error'] = false;
$response['data'] = $result;
$responses[$index] = $response;
} catch (Exception $e) {
$jsonexception = get_exception_info($e);
unset($jsonexception->a);
if (!debugging('', DEBUG_DEVELOPER)) {
unset($jsonexception->debuginfo);
unset($jsonexception->backtrace);
}
$response['error'] = true;
$response['exception'] = $jsonexception;
$responses[$index] = $response;
// Do not process the remaining requests.
break;
}
}
echo json_encode($responses);

1
lib/amd/build/ajax.min.js vendored Normal file
View File

@ -0,0 +1 @@
define(["jquery","core/config"],function(a,b){var c=function(a){var b,c,d=this,e=null,f=0;for(f=0;f<d.length;f++){if(b=d[f],c=a[f],"undefined"==typeof c){e=new Error("missing response");break}if(c.error!==!1){e=c.exception;break}b.deferred.resolve(c.data)}if(null!==e)for(;f<d.length;f++)b=d[f],b.deferred.reject(e)},d=function(a,b){var c=this,d=0;for(d=0;d<c.length;d++){var e=c[d];"undefined"!=typeof e.fail&&e.deferred.reject(b)}};return{call:function(e){var f,g=[],h=[];for(f=0;f<e.length;f++){var i=e[f];g.push({index:f,methodname:i.methodname,args:i.args}),i.deferred=a.Deferred(),h.push(i.deferred.promise()),"undefined"!=typeof i.done&&i.deferred.done(i.done),"undefined"!=typeof i.fail&&i.deferred.fail(i.fail),i.index=f}g=JSON.stringify(g);var j={type:"POST",data:g,context:e,dataType:"json",processData:!1};return a.ajax(b.wwwroot+"/lib/ajax/service.php",j).done(c).fail(d),h}}});

1
lib/amd/build/config.min.js vendored Normal file
View File

@ -0,0 +1 @@
define(function(){return M.cfg});

139
lib/amd/src/ajax.js Normal file
View File

@ -0,0 +1,139 @@
// 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 <http://www.gnu.org/licenses/>.
/**
* 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
* @package core
* @copyright 2015 Damyon Wiese <damyon@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
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.
*
* @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.
*
* @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.
* @param {Object[]} 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.
* @return {Promise{}} Array of promises that will be resolved when the ajax call returns.
*/
call: function(requests) {
var ajaxRequestData = [],
i,
promises = [];
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
};
$.ajax(config.wwwroot + '/lib/ajax/service.php', settings)
.done(requestSuccess)
.fail(requestFail);
return promises;
}
};
});

28
lib/amd/src/config.js Normal file
View File

@ -0,0 +1,28 @@
// 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 <http://www.gnu.org/licenses/>.
/**
* Expose the M.cfg global variable.
*
* @module core/config
* @package core
* @copyright 2015 Damyon Wiese <damyon@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define(function() {
// This module exposes only the raw data from M.cfg;
return /** @alias module:core/config */ M.cfg;
});

View File

@ -77,6 +77,16 @@ class core_external extends external_api {
return $strparams; return $strparams;
} }
/**
* Can this function be called directly from ajax?
*
* @return boolean
* @since Moodle 2.9
*/
public static function get_string_is_allowed_from_ajax() {
return true;
}
/** /**
* Returns description of get_string parameters * Returns description of get_string parameters
* *
@ -153,6 +163,17 @@ class core_external extends external_api {
); );
} }
/**
* Can this function be called directly from ajax?
*
* @return boolean
* @since Moodle 2.9
*/
public static function get_strings_is_allowed_from_ajax() {
return true;
}
/** /**
* Return multiple call to core get_string() * Return multiple call to core get_string()
* *
@ -216,6 +237,16 @@ class core_external extends external_api {
); );
} }
/**
* Can this function be called directly from ajax?
*
* @return boolean
* @since Moodle 2.9
*/
public static function get_component_strings_is_allowed_from_ajax() {
return true;
}
/** /**
* Return all lang strings of a component - call to core get_component_strings(). * Return all lang strings of a component - call to core get_component_strings().
* *

View File

@ -56,6 +56,7 @@ function external_function_info($function, $strictness=MUST_EXIST) {
} }
} }
$function->ajax_method = $function->methodname.'_is_allowed_from_ajax';
$function->parameters_method = $function->methodname.'_parameters'; $function->parameters_method = $function->methodname.'_parameters';
$function->returns_method = $function->methodname.'_returns'; $function->returns_method = $function->methodname.'_returns';
$function->deprecated_method = $function->methodname.'_is_deprecated'; $function->deprecated_method = $function->methodname.'_is_deprecated';
@ -75,6 +76,12 @@ function external_function_info($function, $strictness=MUST_EXIST) {
$function->deprecated = true; $function->deprecated = true;
} }
} }
$function->allowed_from_ajax = false;
if (method_exists($function->classname, $function->ajax_method)) {
if (call_user_func(array($function->classname, $function->ajax_method)) === true) {
$function->allowed_from_ajax = true;
}
}
// fetch the parameters description // fetch the parameters description
$function->parameters_desc = call_user_func(array($function->classname, $function->parameters_method)); $function->parameters_desc = call_user_func(array($function->classname, $function->parameters_method));

View File

@ -811,6 +811,14 @@ EOF;
$documentationhtml .= html_writer::end_tag('span'); $documentationhtml .= html_writer::end_tag('span');
} }
$documentationhtml .= $br . $br; $documentationhtml .= $br . $br;
// Ajax info.
$documentationhtml .= html_writer::start_tag('span', array('style' => 'color:#EA33A6'));
$documentationhtml .= get_string('callablefromajax', 'webservice') . $br;
$documentationhtml .= html_writer::end_tag('span');
$documentationhtml .= $description->allowed_from_ajax ? get_string('yes') : get_string('no');
$documentationhtml .= $br . $br;
if (empty($printableformat)) { if (empty($printableformat)) {
$documentationhtml .= print_collapsible_region_end(true); $documentationhtml .= print_collapsible_region_end(true);
} }