$descparams->atag = $atag; $descparams->mode = get_string('debugnormal', 'admin'); echo get_string('testclientdescription', 'webservice', $descparams); echo $OUTPUT->box_end(); $mform->display(); echo $OUTPUT->footer(); die; } $class = $function . '_form'; $mform = new $class(null, array('authmethod' => $authmethod)); $mform->set_data(array('function' => $function, 'protocol' => $protocol)); if ($mform->is_cancelled()) { redirect('testclient.php'); } else { if ($data = $mform->get_data()) { $functioninfo = external_api::external_function_info($function); // first load lib of selected protocol require_once "{$CFG->dirroot}/webservice/{$protocol}/locallib.php"; $testclientclass = "webservice_{$protocol}_test_client"; if (!class_exists($testclientclass)) { throw new coding_exception('Missing WS test class in protocol ' . $protocol); } $testclient = new $testclientclass(); $serverurl = "{$CFG->wwwroot}/webservice/{$protocol}/"; if ($authmethod == 'simple') { $serverurl .= 'simpleserver.php'; $serverurl .= '?wsusername='******'&wspassword='******'token') { $serverurl .= 'server.php';
/** * This method parses the request input, it needs to get: * 1/ user authentication - username+password or token * 2/ function name * 3/ function parameters */ protected function parse_request() { // Retrieve and clean the POST/GET parameters from the parameters specific to the server. parent::set_web_service_call_settings(); // Get GET and POST parameters. $methodvariables = array_merge($_GET, $_POST); if ($this->authmethod == WEBSERVICE_AUTHMETHOD_USERNAME) { $this->username = isset($methodvariables['wsusername']) ? $methodvariables['wsusername'] : null; unset($methodvariables['wsusername']); $this->password = isset($methodvariables['wspassword']) ? $methodvariables['wspassword'] : null; unset($methodvariables['wspassword']); } else { $this->token = isset($methodvariables['wstoken']) ? $methodvariables['wstoken'] : null; unset($methodvariables['wstoken']); } // Get the XML-RPC request data. $rawpostdata = file_get_contents("php://input"); $methodname = null; // Decode the request to get the decoded parameters and the name of the method to be called. $decodedparams = xmlrpc_decode_request($rawpostdata, $methodname); $methodinfo = external_api::external_function_info($methodname); $methodparams = array_keys($methodinfo->parameters_desc->keys); // Add the decoded parameters to the methodvariables array. if (is_array($decodedparams)) { foreach ($decodedparams as $index => $param) { // See MDL-53962 - XML-RPC requests will usually be sent as an array (as in, one with indicies). // We need to use a bit of "magic" to add the correct index back. Zend used to do this for us. $methodvariables[$methodparams[$index]] = $param; } } $this->functionname = $methodname; $this->parameters = $methodvariables; }
* Web services API documentation * * @package webservice * @copyright 2011 Moodle Pty Ltd (http://moodle.com) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @author Jerome Mouneyrac */ require_once '../../config.php'; require_once $CFG->libdir . '/adminlib.php'; require $CFG->dirroot . '/webservice/lib.php'; admin_externalpage_setup('webservicedocumentation'); // get all the function descriptions $functions = $DB->get_records('external_functions', array(), 'name'); $functiondescs = array(); foreach ($functions as $function) { $functiondescs[$function->name] = external_api::external_function_info($function); } //display the documentation for all documented protocols, //regardless if they are activated or not $protocols = array(); $protocols['rest'] = true; $protocols['xmlrpc'] = true; /// Check if we are in printable mode $printableformat = optional_param('print', false, PARAM_BOOL); /// OUTPUT echo $OUTPUT->header(); $renderer = $PAGE->get_renderer('core', 'webservice'); echo $renderer->documentation_html($functiondescs, $printableformat, $protocols, array(), $PAGE->url); /// trigger browser print operation if (!empty($printableformat)) { $PAGE->requires->js_function_call('window.print', array());
/** * Returns detailed function information * * @deprecated since Moodle 3.1 * @param string|object $function name of external function or record from external_function * @param int $strictness IGNORE_MISSING means compatible mode, false returned if record not found, debug message if more found; * MUST_EXIST means throw exception if no record or multiple records found * @return stdClass description or false if not found or exception thrown * @since Moodle 2.0 */ function external_function_info($function, $strictness = MUST_EXIST) { debugging('external_function_info() is deprecated. Please use external_api::external_function_info() instead.', DEBUG_DEVELOPER); return external_api::external_function_info($function, $strictness); }
/** * @dataProvider all_external_info_provider */ public function test_all_external_info($f) { $desc = external_api::external_function_info($f); $this->assertNotEmpty($desc->name); $this->assertNotEmpty($desc->classname); $this->assertNotEmpty($desc->methodname); $this->assertEquals($desc->component, clean_param($desc->component, PARAM_COMPONENT)); $this->assertInstanceOf('external_function_parameters', $desc->parameters_desc); if ($desc->returns_desc != null) { $this->assertInstanceOf('external_description', $desc->returns_desc); } }
/** * Returns a virtual method code for a web service function. * * @param stdClass $function a record from external_function * @return string The PHP code of the virtual method. * @throws coding_exception * @throws moodle_exception */ protected function get_virtual_method_code($function) { $function = external_api::external_function_info($function); // Parameters and their defaults for the method signature. $paramanddefaults = array(); // Parameters for external lib call. $params = array(); $paramdesc = array(); // The method's input parameters and their respective types. $inputparams = array(); // The method's output parameters and their respective types. $outputparams = array(); foreach ($function->parameters_desc->keys as $name => $keydesc) { $param = '$' . $name; $paramanddefault = $param; if ($keydesc->required == VALUE_OPTIONAL) { // It does not make sense to declare a parameter VALUE_OPTIONAL. VALUE_OPTIONAL is used only for array/object key. throw new moodle_exception('erroroptionalparamarray', 'webservice', '', $name); } else { if ($keydesc->required == VALUE_DEFAULT) { // Need to generate the default, if there is any. if ($keydesc instanceof external_value) { if ($keydesc->default === null) { $paramanddefault .= ' = null'; } else { switch ($keydesc->type) { case PARAM_BOOL: $default = (int) $keydesc->default; break; case PARAM_INT: $default = $keydesc->default; break; case PARAM_FLOAT: $default = $keydesc->default; break; default: $default = "'{$keydesc->default}'"; } $paramanddefault .= " = {$default}"; } } else { // Accept empty array as default. if (isset($keydesc->default) && is_array($keydesc->default) && empty($keydesc->default)) { $paramanddefault .= ' = array()'; } else { // For the moment we do not support default for other structure types. throw new moodle_exception('errornotemptydefaultparamarray', 'webservice', '', $name); } } } } $params[] = $param; $paramanddefaults[] = $paramanddefault; $type = $this->get_phpdoc_type($keydesc); $inputparams[$name]['type'] = $type; $paramdesc[] = '* @param ' . $type . ' $' . $name . ' ' . $keydesc->desc; } $paramanddefaults = implode(', ', $paramanddefaults); $paramdescstr = implode("\n ", $paramdesc); $serviceclassmethodbody = $this->service_class_method_body($function, $params); if (empty($function->returns_desc)) { $return = '* @return void'; } else { $type = $this->get_phpdoc_type($function->returns_desc); $outputparams['return']['type'] = $type; $return = '* @return ' . $type . ' ' . $function->returns_desc->desc; } // Now create the virtual method that calls the ext implementation. $code = <<<EOD /** * {$function->description}. * {$paramdescstr} {$return} */ public function {$function->name}({$paramanddefaults}) { {$serviceclassmethodbody} } EOD; // Prepare the method information. $methodinfo = new stdClass(); $methodinfo->name = $function->name; $methodinfo->inputparams = $inputparams; $methodinfo->outputparams = $outputparams; $methodinfo->description = $function->description; // Add the method information into the list of service methods. $this->servicemethods[] = $methodinfo; return $code; }
function definition() { global $CFG; $mform = $this->_form; $data = $this->_customdata; $mform->addElement('header', 'addfunction', get_string('addfunctions', 'webservice')); require_once $CFG->dirroot . "/webservice/lib.php"; $webservicemanager = new webservice(); $functions = $webservicemanager->get_not_associated_external_functions($data['id']); //we add the descriptions to the functions foreach ($functions as $functionid => $functionname) { //retrieve full function information (including the description) $function = external_api::external_function_info($functionname); if (empty($function->deprecated)) { $functions[$functionid] = $function->name . ':' . $function->description; } else { // Exclude the deprecated ones. unset($functions[$functionid]); } } $mform->addElement('searchableselector', 'fids', get_string('name'), $functions, array('multiple')); $mform->addRule('fids', get_string('required'), 'required', null, 'client'); $mform->addElement('hidden', 'id'); $mform->setType('id', PARAM_INT); $mform->addElement('hidden', 'action'); $mform->setType('action', PARAM_ALPHANUMEXT); $this->add_action_buttons(true, get_string('addfunctions', 'webservice')); $this->set_data($data); }
/** * Test init_service_class(). */ public function test_init_service_class() { global $DB, $USER; $this->resetAfterTest(true); // Set current user. $this->setAdminUser(); // Add a web service. $webservice = new stdClass(); $webservice->name = 'Test web service'; $webservice->enabled = true; $webservice->restrictedusers = false; $webservice->component = 'moodle'; $webservice->timecreated = time(); $webservice->downloadfiles = true; $webservice->uploadfiles = true; $externalserviceid = $DB->insert_record('external_services', $webservice); // Add token. $externaltoken = new stdClass(); $externaltoken->token = 'testtoken'; $externaltoken->tokentype = 0; $externaltoken->userid = $USER->id; $externaltoken->externalserviceid = $externalserviceid; $externaltoken->contextid = 1; $externaltoken->creatorid = $USER->id; $externaltoken->timecreated = time(); $DB->insert_record('external_tokens', $externaltoken); // Add a function to the service. $wsmethod = new stdClass(); $wsmethod->externalserviceid = $externalserviceid; $wsmethod->functionname = 'core_course_get_contents'; $DB->insert_record('external_services_functions', $wsmethod); // Initialise the dummy web service. $dummy = new webservice_dummy(WEBSERVICE_AUTHMETHOD_PERMANENT_TOKEN); // Set the token. $dummy->set_token($externaltoken->token); // Run the web service. $dummy->run(); // Get service methods and structs. $servicemethods = $dummy->get_service_methods(); $servicestructs = $dummy->get_service_structs(); $this->assertNotEmpty($servicemethods); // The function core_course_get_contents should be only the only web service function in the moment. $this->assertEquals(1, count($servicemethods)); // The function core_course_get_contents doesn't have a struct class, so the list of service structs should be empty. $this->assertEmpty($servicestructs); // Add other functions to the service. // The function core_comment_get_comments has one struct class in its output. $wsmethod->functionname = 'core_comment_get_comments'; $DB->insert_record('external_services_functions', $wsmethod); // The function core_grades_update_grades has one struct class in its input. $wsmethod->functionname = 'core_grades_update_grades'; $DB->insert_record('external_services_functions', $wsmethod); // Run the web service again. $dummy->run(); // Get service methods and structs. $servicemethods = $dummy->get_service_methods(); $servicestructs = $dummy->get_service_structs(); $this->assertEquals(3, count($servicemethods)); $this->assertEquals(2, count($servicestructs)); // Check the contents of service methods. foreach ($servicemethods as $method) { // Get the external function info. $function = external_api::external_function_info($method->name); // Check input params. foreach ($function->parameters_desc->keys as $name => $keydesc) { $this->check_params($method->inputparams[$name]['type'], $keydesc, $servicestructs); } // Check output params. $this->check_params($method->outputparams['return']['type'], $function->returns_desc, $servicestructs); // Check description. $this->assertEquals($function->description, $method->description); } }
/** * Display a list of functions for a given service * If the service is built-in, do not display remove/add operation (read-only) * * @param array $functions list of functions * @param stdClass $service the given service * @return string the table html + add operation html */ public function admin_service_function_list($functions, $service) { global $CFG; if (!empty($functions)) { $table = new html_table(); $table->head = array(get_string('function', 'webservice'), get_string('description'), get_string('requiredcaps', 'webservice')); $table->align = array('left', 'left', 'left'); $table->size = array('15%', '40%', '40%'); $table->width = '100%'; $table->align[] = 'left'; //display remove function operation (except for build-in service) if (empty($service->component)) { $table->head[] = get_string('edit'); $table->align[] = 'center'; } $anydeprecated = false; foreach ($functions as $function) { $function = external_api::external_function_info($function); if (!empty($function->deprecated)) { $anydeprecated = true; } $requiredcaps = html_writer::tag('div', empty($function->capabilities) ? '' : $function->capabilities, array('class' => 'functiondesc')); $description = html_writer::tag('div', $function->description, array('class' => 'functiondesc')); //display remove function operation (except for build-in service) if (empty($service->component)) { $removeurl = new moodle_url('/' . $CFG->admin . '/webservice/service_functions.php', array('sesskey' => sesskey(), 'fid' => $function->id, 'id' => $service->id, 'action' => 'delete')); $removelink = html_writer::tag('a', get_string('removefunction', 'webservice'), array('href' => $removeurl)); $table->data[] = array($function->name, $description, $requiredcaps, $removelink); } else { $table->data[] = array($function->name, $description, $requiredcaps); } } $html = html_writer::table($table); } else { $html = get_string('nofunctions', 'webservice') . html_writer::empty_tag('br'); } //display add function operation (except for build-in service) if (empty($service->component)) { if (!empty($anydeprecated)) { debugging('This service uses deprecated functions, replace them by the proposed ones and update your client/s.', DEBUG_DEVELOPER); } $addurl = new moodle_url('/' . $CFG->admin . '/webservice/service_functions.php', array('sesskey' => sesskey(), 'id' => $service->id, 'action' => 'add')); $html .= html_writer::tag('a', get_string('addfunctions', 'webservice'), array('href' => $addurl)); } return $html; }