navigation MDL-20242 Fixed bug whereby sections that no longer exist were shown
[moodle.git] / webservice / lib.php
CommitLineData
06e7fadc 1<?php
2/**
3 * Moodle - Modular Object-Oriented Dynamic Learning Environment
4 * http://moodle.com
5 *
6 * LICENSE
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details:
17 *
18 * http://www.gnu.org/copyleft/gpl.html
19 *
20 * @category Moodle
21 * @package webservice
22 * @copyright Copyright (c) 1999 onwards Martin Dougiamas http://dougiamas.com
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL License
24 */
25
24350e06 26require_once(dirname(dirname(__FILE__)) . '/lib/formslib.php');
06e7fadc 27
28/**
29 * web service library
30 */
31final class webservice_lib {
32
886d7556 33/**
34 * Return list of all web service protocol into the webservice folder
35 * @global <type> $CFG
36 * @return <type>
37 */
06e7fadc 38 public static function get_list_protocols() {
39 global $CFG;
40 $protocols = array();
41 $directorypath = $CFG->dirroot . "/webservice";
42 if( $dh = opendir($directorypath)) {
886d7556 43 while( false !== ($file = readdir($dh))) {
06e7fadc 44 if( $file == '.' || $file == '..' || $file == 'CVS') { // Skip '.' and '..'
45 continue;
46 }
47 $path = $directorypath . '/' . $file;
40f024c9 48 ///browse the subfolder
06e7fadc 49 if( is_dir($path) ) {
fbe52a39 50 if ($file != 'db') { //we don't want to browse the 'db' subfolder of webservice folder
886d7556 51 require_once($path."/lib.php");
52 $classname = $file."_server";
53 $protocols[] = new $classname;
fbe52a39 54 }
06e7fadc 55 }
40f024c9 56 ///retrieve api.php file
886d7556 57 else {
06e7fadc 58 continue;
59 }
60 }
61 closedir($dh);
62 }
63 return $protocols;
64 }
65
66 /**
67 * Temporary Authentication method to be modified/removed
68 * @global <type> $DB
69 * @param <type> $token
70 * @return <type>
71 */
72 public static function mock_check_token($token) {
886d7556 73 //fake test
fa0797ec 74 if ($token == 456) {
886d7556 75 ///retrieve the user
06e7fadc 76 global $DB;
77 $user = $DB->get_record('user', array('username'=>'wsuser', 'mnethostid'=>1));
78
79 if (empty($user)) {
80 return false;
81 }
82
83 return $user;
84 } else {
85 return false;
86 }
87 }
88
24350e06 89 /**
90 * Retrieve all external.php from Moodle (except the one of the exception list)
91 * @param <type> $
92 * @param <type> $directorypath
93 * @return boolean true if n
94 */
886d7556 95 public static function setListApiFiles( &$files, $directorypath ) {
24350e06 96 global $CFG;
97
886d7556 98 if(is_dir($directorypath)) { //check that we are browsing a folder not a file
24350e06 99
886d7556 100 if( $dh = opendir($directorypath)) {
101 while( false !== ($file = readdir($dh))) {
24350e06 102
103 if( $file == '.' || $file == '..') { // Skip '.' and '..'
104 continue;
105 }
106 $path = $directorypath . '/' . $file;
40f024c9 107 ///browse the subfolder
24350e06 108 if( is_dir($path) ) {
40f024c9 109 webservice_lib::setListApiFiles($files, $path);
24350e06 110 }
40f024c9 111 ///retrieve api.php file
24350e06 112 else if ($file == "external.php") {
886d7556 113 $files[] = $path;
114 }
24350e06 115 }
116 closedir($dh);
117
118 }
119 }
120
121 }
122
886d7556 123 public static function services_discovery() {
124 global $CFG, $DB;
125 $externalfiles = array();
126 webservice_lib::setListApiFiles($externalfiles, $CFG->dirroot);
127
128 //retrieve all saved services
129 $services = $DB->get_records('external_services', array('custom' => 0)); //we only retrieve not custom service
130 $dbservices = array();
131 foreach ($services as $service) {
132 $dbservices[$service->name] = false; //value false will define obsolote status
133 //once we parse all services from the external files
134 }
135
136 //retrieve all saved servicefunction association including their function name,
137 //service name, function id and service id
138
139 $servicesfunctions = $DB->get_records_sql("SELECT fs.id as id, s.name as servicename, s.id as serviceid, f.name as functionname, f.id as functionid
140 FROM {external_services} s, {external_functions} f, {external_services_functions} fs
141 WHERE fs.externalserviceid = s.id AND fs.externalfunctionid = f.id AND s.custom = 0");
142 $dbservicesfunctions = array();
143 foreach ($servicesfunctions as $servicefunction) {
144 $dbservicesfunctions[$servicefunction->servicename][$servicefunction->functionname] = array('serviceid' => $servicefunction->serviceid,
145 'functionid' => $servicefunction->functionid,
146 'id' => $servicefunction->id,
147 'notobsolete' => false);
148 //once we parse all services from the external files
149 }
150
151 foreach ($externalfiles as $file) {
152 require($file);
153 $classpath = substr($file,strlen($CFG->dirroot)+1); //remove the dir root + / from the file path
154 $classpath = substr($classpath,0,strlen($classpath) - 13); //remove /external.php from the classpath
155 $classpath = str_replace('/','_',$classpath); //convert all / into _
156 $classname = $classpath."_external";
157 $api = new $classname();
158 if (method_exists($api, 'get_descriptions')) {
159 $descriptions = $api->get_descriptions();
160
161 //retrieve all saved function into the DB for this specific external file/component
162 $functions = $DB->get_records('external_functions', array('component' => $classpath));
163 //remove the obsolete ones
164 $dbfunctions = array();
165 foreach ($functions as $function) {
166 $dbfunctions[$function->name] = false; //value false is not important we just need the key
167 if (!array_key_exists($function->name, $descriptions)) {
168 //remove all obsolete function from the db
169 $DB->delete_records('external_functions', array('name' => $function->name, 'component' => $classpath));
170 }
171 }
172
173 foreach ($descriptions as $functionname => $functiondescription) {
174
175
176
177 //only create the one not already saved into the database
178 if (!array_key_exists($functionname, $dbfunctions)) {
179 $newfunction = new object();
180 $newfunction->component = $classpath;
181 $newfunction->name = $functionname;
182 $newfunction->enabled = 0;
183 $DB->insert_record('external_functions', $newfunction);
184 }
185
186 //check if the service is into the database
187 if (array_key_exists('service', $functiondescription) && !empty($functiondescription['service'])) { //check that the service has been set in the description
188 if (!array_key_exists($functiondescription['service'], $dbservices)) {
189 $newservice = new object();
190 $newservice->name = $functiondescription['service'];
191 $newservice->enable = 0;
192 $newservice->custom = 0;
193 $DB->insert_record('external_services', $newservice);
194 }
195 $dbservices[$functiondescription['service']] = true; //mark the service as not obsolete
196 //and add it if it wasn't in the list
197 }
198 else {
199 $errors = new object();
200 $errors->classname = $classname;
201 $errors->functionname = $functionname;
202 throw new moodle_exception("wsdescriptionserviceisempty",'','', $errors);
203
204 }
205
206
207 //check if the couple service/function is into the database
208 if (!array_key_exists($functiondescription['service'], $dbservicesfunctions) || !array_key_exists($functionname, $dbservicesfunctions[$functiondescription['service']])) {
209 $newassociation = new object();
210 $newassociation->externalserviceid = $DB->get_field('external_services','id',array('name' => $functiondescription['service']));
211 $newassociation->externalfunctionid = $DB->get_field('external_functions','id',array('name' => $functionname, 'component' => $classpath));
212 $DB->insert_record('external_services_functions', $newassociation);
213 }
214 $dbservicesfunctions[$functiondescription['service']][$functionname]['notobsolete'] = true;
215 }
216
217
218 }
219 else {
220 throw new moodle_exception("wsdoesntextendbaseclass",'','', $classname);
221 }
222 }
223
224 //remove all obsolete service (not the custom ones)
225 foreach ($dbservices as $servicename => $notobsolete) {
226 if (!$notobsolete) {
227 $DB->delete_records('external_services', array('name' => $servicename));
228 }
229 }
230
231 //remove all obsolete association (not the custom ones)
232 foreach ($dbservicesfunctions as $servicename => $servicefunctions ) {
233 foreach ($servicefunctions as $functioname => $servicefunction) {
234 if (!$servicefunction['notobsolete']) {
235 $DB->delete_records('external_services_functions', array('id' => $servicefunction['id']));
236 }
237 }
238 }
239 }
240
fa0797ec 241 /**
242 * Check if the Moodle site has the web service protocol enable
243 * @global object $CFG
244 * @param string $protocol
245 */
886d7556 246 function display_webservices_availability($protocol) {
fa0797ec 247 global $CFG;
248
249 $available = true;
250
251 echo get_string('webservicesenable','webservice').": ";
252 if (empty($CFG->enablewebservices)) {
253 echo "<strong style=\"color:red\">".get_string('fail','webservice')."</strong>";
254 $available = false;
255 } else {
256 echo "<strong style=\"color:green\">".get_string('ok','webservice')."</strong>";
257 }
258 echo "<br/>";
259
260 foreach(webservice_lib::get_list_protocols() as $wsprotocol) {
f7631e73 261 if (strtolower($wsprotocol->get_protocolid()) == strtolower($protocol)) {
262 echo get_string('protocolenable','webservice',array($wsprotocol->get_protocolid())).": ";
263 if ( get_config($wsprotocol-> get_protocolid(), "enable")) {
fa0797ec 264 echo "<strong style=\"color:green\">".get_string('ok','webservice')."</strong>";
265 } else {
266 echo "<strong style=\"color:red\">".get_string('fail','webservice')."</strong>";
267 $available = false;
268 }
269 echo "<br/>";
270 continue;
271 }
272 }
273
274 //check debugging
275 if ($CFG->debugdisplay) {
276 echo "<strong style=\"color:red\">".get_string('debugdisplayon','webservice')."</strong>";
277 $available = false;
278 }
279
280 return $available;
281 }
282
06e7fadc 283}
284
285/**
286 * Web Service server base class
287 */
288abstract class webservice_server {
289
886d7556 290/**
291 * Web Service Protocol name (eg. SOAP, REST, XML-RPC,...)
292 * @var String
293 */
06e7fadc 294 private $protocolname;
295
f7631e73 296 /**
297 * Web Service Protocol id (eg. soap, rest, xmlrpc...)
298 * @var String
299 */
300 private $protocolid;
301
06e7fadc 302 public function __construct() {
303 }
304
305 abstract public function run();
306
307 public function get_protocolname() {
308 return $this->protocolname;
309 }
310
f7631e73 311 public function get_protocolid() {
312 return $this->protocolid;
313 }
314
06e7fadc 315 public function set_protocolname($protocolname) {
316 $this->protocolname = $protocolname;
317 }
318
f7631e73 319 public function set_protocolid($protocolid) {
320 $this->protocolid = $protocolid;
321 }
322
06e7fadc 323 public function get_enable() {
f7631e73 324 return get_config($this->get_protocolid(), "enable");
06e7fadc 325 }
326
327 public function set_enable($enable) {
f7631e73 328 set_config("enable", $enable, $this->get_protocolid());
329 }
330
331 /**
332 * Names of the server settings
333 * @return array
334 */
335 public static function get_setting_names() {
336 return array();
337 }
338
339 public function settings_form(&$mform) {
06e7fadc 340 }
341
342}
343
344/**
345 * Temporary authentication class to be removed/modified
346 */
347class ws_authentication {
886d7556 348/**
349 *
350 * @param object|struct $params
351 * @return integer
352 */
ebcc6bd3 353 function get_token($params) {
354 $params->username = clean_param($params->username, PARAM_ALPHANUM);
355 $params->password = clean_param($params->password, PARAM_ALPHANUM);
356 if ($params->username == 'wsuser' && $params->password == 'wspassword') {
fa0797ec 357 return '456';
06e7fadc 358 } else {
359 throw new moodle_exception('wrongusernamepassword');
886d7556 360 }
06e7fadc 361 }
362}
363
24350e06 364/**
365 * Form for web service user settings (administration)
366 */
367final class wsuser_form extends moodleform {
368 protected $username;
369
370 /**
371 * Definition of the moodleform
372 */
373 public function definition() {
374 global $DB;
375 $this->username = $this->_customdata['username'];
376 $mform =& $this->_form;
40f024c9 377
24350e06 378 $mform->addElement('hidden', 'username', $this->username);
379 $param = new stdClass();
380 $param->username = $this->username;
381 $wsuser = $DB->get_record("user", array("username" => $this->username));
382
383 $mform->addElement('text', 'ipwhitelist', get_string('ipwhitelist', 'admin'), array('value'=>get_user_preferences("ipwhitelist", "", $wsuser->id),'size' => '40'));
384 $mform->addElement('static', null, '', get_string('ipwhitelistdesc','admin', $param));
385
386 $this->add_action_buttons(true, get_string('savechanges','admin'));
387 }
388}
389
f7631e73 390/**
391 * Form for web service server settings (administration)
392 */
393final class wssettings_form extends moodleform {
394 protected $settings;
395
396 /**
397 * Definition of the moodleform
398 */
399 public function definition() {
400 global $DB,$CFG;
401 $settings = $this->_customdata['settings'];
402 $mform =& $this->_form;
403
404 $mform->addElement('hidden', 'settings', $settings);
405 $param = new stdClass();
406
407 require_once($CFG->dirroot . '/webservice/'. $settings . '/lib.php');
408 $servername = $settings.'_server';
409 $server = new $servername();
410 $server->settings_form($mform);
411
412 // set the data if we have some.
413 $data = array();
414 $option_names = $server->get_setting_names();
415 foreach ($option_names as $config) {
416 $data[$config] = get_config($settings, $config);
417 }
418 $this->set_data($data);
419
420
421 $this->add_action_buttons(true, get_string('savechanges','admin'));
422 }
423}
424
06e7fadc 425?>