PageRenderTime 71ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 1ms

/wspp/server.class.php

https://bitbucket.org/systime/screening2
PHP | 4139 lines | 2808 code | 451 blank | 880 comment | 600 complexity | 0da73627ea8e2c09e55977d9d50ec4d5 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, GPL-3.0, BSD-3-Clause, LGPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. // $Id: server.class.php,v 1.14 2010/10/26 13:50:10 ppollet Exp $
  3. /**
  4. * Base class for web services server layer. PP 5 ONLY.
  5. *
  6. * @package Web Services
  7. * @version $Id: server.class.php,v 1.14 2010/10/26 13:50:10 ppollet Exp $
  8. * @author Open Knowledge Technologies - http://www.oktech.ca/
  9. * @author Justin Filip <jfilip@oktech.ca> v 1.4
  10. * @author Patrick Pollet <patrick.pollet@insa-lyon.fr> v 1.5, v 1.6, v 1.7
  11. * @author
  12. */
  13. /* rev history
  14. @see revisions.txt
  15. **/
  16. require_once ('../config.php');
  17. require_once ('wslib.php');
  18. require_once ('filterlib.php');
  19. /// increase memory limit (PHP 5.2 does different calculation, we need more memory now)
  20. // j'ai 11000 comptes
  21. @ raise_memory_limit("192M"); //fonction de lib/setuplib.php incluse via config.php
  22. //set_time_limit(0);
  23. //define('DEBUG', true); rev. 1.5.16 already set (or not) in MoodleWS.php
  24. define('cal_show_global', 1);
  25. define('cal_show_course', 2);
  26. define('cal_show_group', 4);
  27. define('cal_show_user', 8);
  28. /**
  29. * The main server class.
  30. *
  31. * The only methods that need to be extended in a child class are error() and any of
  32. * the service methods which need special transport-protocol specific handling of
  33. * input and / or output data (ie non simple type returns)
  34. *
  35. */
  36. class server {
  37. var $version = 2010101000; // also Moodle 2.0 compatible
  38. var $using17;
  39. var $using19 = false;
  40. /**
  41. * Constructor method.
  42. *
  43. * @uses $CFG
  44. * @param none
  45. * @return none
  46. */
  47. function server () {
  48. global $CFG;
  49. $this->debug_output("Server init...");
  50. $this->debug_output(' Version: ' . $this->version);
  51. $this->debug_output(' Session Timeout: ' . $this->sessiontimeout);
  52. if (! $CFG->wspp_using_moodle20) {
  53. $this->using17 = file_exists($CFG->libdir . '/accesslib.php');
  54. $this->using19 = file_exists($CFG->libdir . '/grouplib.php');
  55. //Check for any DB upgrades.
  56. if (empty ($CFG->webservices_version)) {
  57. $this->upgrade(0);
  58. } else
  59. if ($CFG->webservices_version < $this->version) {
  60. $this->upgrade($CFG->webservices_version);
  61. }
  62. } else {
  63. $this->using17 = $this->using19 = true;
  64. }
  65. // setup default values if not set in admin screens (see admin/wspp.php)
  66. if (empty ($CFG->ws_sessiontimeout))
  67. $CFG->ws_sessiontimeout = 1800;
  68. $this->sessiontimeout = $CFG->ws_sessiontimeout;
  69. if (!isset ($CFG->ws_logoperations))
  70. $CFG->ws_logoperations = 1;
  71. if (!isset ($CFG->ws_logerrors))
  72. $CFG->ws_logerrors = 0;
  73. if (!isset ($CFG->ws_logdetailedoperations))
  74. $CFG->ws_logdetailledoperations = 0;
  75. if (!isset ($CFG->ws_debug))
  76. $CFG->ws_debug = 0;
  77. if (!isset ($CFG->ws_enforceipcheck))
  78. $CFG->ws_enforceipcheck = 0; // rev 1.6.1 off by default++++
  79. }
  80. /**
  81. * Performs an upgrade of the webservices system.
  82. * Moodle < 2.0 ONLY
  83. * @uses $CFG
  84. * @param int $oldversion The old version number we are upgrading from.
  85. * @return boolean True if successful, False otherwise.
  86. */
  87. private function upgrade($oldversion) {
  88. global $CFG;
  89. if ($CFG->wspp_using_moodle20)
  90. return $this->error(get_string('ws_not_installed_moodle20', 'local_wspp'));
  91. $this->debug_output('Starting WS upgrade from version ' . $oldversion . 'to version ' . $this->version);
  92. $return = true;
  93. require_once ($CFG->libdir . '/ddllib.php');
  94. if ($oldversion < 2006050800) {
  95. $return = install_from_xmldb_file($CFG->dirroot . '/wspp/db/install.xml');
  96. } else {
  97. if ($oldversion < 2007051000) {
  98. $table = new XMLDBTable('webservices_sessions');
  99. $field = new XMLDBField('ip');
  100. // since table exists, keep NULL as true and no default value !
  101. // otherwise XMLDB do not do the change but return true ...
  102. $field->setAttributes(XMLDB_TYPE_CHAR, '64');
  103. $return = add_field($table, $field, false, false);
  104. }
  105. }
  106. if ($return) {
  107. set_config('webservices_version', $this->version);
  108. $this->debug_output('Upgraded from ' . $oldversion . ' to ' . $this->version);
  109. } else {
  110. $this->debug_output('ERROR: Could not upgrade to version ' . $this->version);
  111. }
  112. return $return;
  113. }
  114. /**
  115. * Creates a new session key.
  116. *
  117. * @param none
  118. * @return string A 32 character session key.
  119. */
  120. private function add_session_key() {
  121. $time = (string) time();
  122. $randstr = (string) random_string(10);
  123. /// XOR the current time and a random string.
  124. $str = $time;
  125. $str ^= $randstr;
  126. /// Use the MD5 sum of this random 10 character string as the session key.
  127. return md5($str);
  128. }
  129. /**
  130. * Validate's that a client has an existing session.
  131. *
  132. * @param int $client The client session ID.
  133. * @param string $sesskey The client session key.
  134. * @return boolean True if the client is valid, False otherwise.
  135. */
  136. private function validate_client($client = 0, $sesskey = '', $operation = '') {
  137. global $USER, $CFG;
  138. //return true;
  139. // rev 1.6.3 added extra securityu checks
  140. $client = clean_param($client, PARAM_INT);
  141. $sesskey = clean_param($sesskey, PARAM_ALPHANUM);
  142. /// We can't validate a session that hasn't even been initialized yet.
  143. if (!$sess = ws_get_record('webservices_sessions', 'id', $client, 'sessionend', 0, 'verified', 1)) {
  144. return false;
  145. }
  146. /// Validate this session.
  147. if ($sesskey != $sess->sessionkey) {
  148. return false;
  149. }
  150. // rev 1.6 make sure the session has not timed out
  151. if ($sess->sessionbegin + $this->sessiontimeout < time()) {
  152. $sess->sessionend = time();
  153. ws_update_record('webservices_sessions', $sess);
  154. return false;
  155. }
  156. $USER->id = $sess->userid;
  157. $USER->username = '';
  158. $USER->mnethostid = $CFG->mnet_localhost_id; //Moodle 1.95+ build sept 2009
  159. $USER->ip= getremoteaddr();
  160. unset ($USER->access); // important for get_my_courses !
  161. $this->debug_output("validate_client OK $operation $client user=" . print_r($USER, true));
  162. //$this->debug_output(print_r($CFG,true));
  163. //LOG INTO MOODLE'S LOG
  164. if ($operation && $CFG->ws_logoperations)
  165. add_to_log(SITEID, 'webservice', 'webservice pp', '', $operation);
  166. return true;
  167. }
  168. /**
  169. * Sends an FATAL error response back to the client.
  170. *
  171. * @todo Override in protocol-specific server subclass, e.g. by throwing a PHP exception
  172. * @param string $msg The error message to return.
  173. * @return An object with the error message string.(required by mdl_soapserver)
  174. */
  175. protected function error($msg) {
  176. global $CFG;
  177. $res = new StdClass();
  178. $res->error = $msg;
  179. if ($CFG->ws_logerrors)
  180. add_to_log(SITEID, 'webservice', 'webservice pp', '', 'error :' . $msg);
  181. $this->debug_output("server.soap fatal error : $msg ". getremoteaddr());
  182. return $res;
  183. }
  184. /**
  185. * return and object with error attribute set
  186. * this record will be inserted in client array of responses
  187. * do not override in protocol-specific server subclass.
  188. */
  189. private function non_fatal_error($msg) {
  190. $res = new StdClass();
  191. $res->error = $msg;
  192. $this->debug_output("server.soap non fatal error : $msg");
  193. return $res;
  194. }
  195. /**
  196. * Do server-side debugging output (to file).
  197. *
  198. * @uses $CFG
  199. * @param string $output Debugging output.
  200. * @return void
  201. */
  202. function debug_output($output) {
  203. global $CFG;
  204. if ($CFG->ws_debug) {
  205. $fp = fopen($CFG->dataroot . '/debug.out', 'a');
  206. fwrite($fp, "[" . time() . "] $output\n");
  207. fflush($fp);
  208. fclose($fp);
  209. }
  210. }
  211. /**
  212. * check that current ws user has the required capability
  213. * @param string capability
  214. * @param string type on context CONTEXT_SYSTEM, CONTEXT_COURSE ....
  215. * @param object moodle's id
  216. * @param int $userid : user to chcek, default me
  217. */
  218. private function has_capability($capability, $context_type, $instance_id,$userid=NULL) {
  219. global $USER;
  220. $context = get_context_instance($context_type, $instance_id);
  221. if (empty($userid)) { // we must accept null, 0, '0', '' etc. in $userid
  222. $userid = $USER->id;
  223. }
  224. return has_capability($capability, $context, $userid);
  225. }
  226. /**
  227. * Validates a client's login request.
  228. *
  229. * @uses $CFG
  230. * @param array $input Input data from the client request object.
  231. * @return array Return data (client record ID and session key) to be
  232. * converted into a specific data format for sending to the
  233. * client.
  234. */
  235. function login($username, $password) {
  236. global $CFG;
  237. if (!empty ($CFG->ws_disable))
  238. return $this->error(get_string('ws_accessdisabled', 'local_wspp'));
  239. if (!$this->using17)
  240. return $this->error(get_string('ws_nomoodle16', 'local_wspp'));
  241. $userip = getremoteaddr(); // rev 1.5.4
  242. if (!empty($CFG->ws_enforceipcheck)) {
  243. if (!record_exists('webservices_clients_allow','client',$userip))
  244. return $this->error(get_string('ws_accessrestricted', 'local_wspp',$userip));
  245. }
  246. // rev 1.6.3 added extra security checks
  247. $username = clean_param($username, PARAM_NOTAGS);
  248. $password = clean_param($password, PARAM_NOTAGS);
  249. /// Use Moodle authentication.
  250. /// FIRST make sure user exists , otherwise account WILL be created with CAS authentification ....
  251. if (!$knownuser = ws_get_record('user', 'username', $username)) {
  252. return $this->error(get_string('ws_invaliduser', 'local_wspp'));
  253. }
  254. //$this->debug_output(print_r($knownuser, true));
  255. $user=false;
  256. //revision 1.6.1 try to use a custom auth plugin
  257. if (!exists_auth_plugin("webservice") || ! is_enabled_auth("webservice")) {
  258. $this->debug_output('internal ');
  259. /// also make sure internal_authentication is used (a limitation to fix ...)
  260. if (!is_internal_auth($knownuser->auth)) {
  261. return $this->error(get_string('ws_invaliduser', 'local_wspp'));
  262. }
  263. // regular manual authentification (should not be allowed !)
  264. $user = authenticate_user_login(addslashes($username), $password);
  265. $this->debug_output('return of a_u_l'. print_r($user,true));
  266. }
  267. else {
  268. $this->debug_output('auth plugin');
  269. $auth=get_auth_plugin("webservice");
  270. if ($auth->user_login_webservice($username,$password)) {
  271. $user=$knownuser;
  272. }
  273. }
  274. if (($user === false) || ($user && $user->id == 0) || isguestuser($user)) {
  275. return $this->error(get_string('ws_invaliduser', 'local_wspp'));
  276. }
  277. //$this->debug_output(print_r($user,true));
  278. /// Verify that an active session does not already exist for this user.
  279. $userip = getremoteaddr(); // rev 1.5.4
  280. $sql = "userid = {$user->id} AND verified = 1 AND
  281. ip='$userip' AND sessionend = 0 AND
  282. (" . time() . "- sessionbegin) < " . $this->sessiontimeout;
  283. //$this->debug_output($sql);
  284. if ($sess = ws_get_record_select('webservices_sessions',$sql)) {
  285. //return $this->error('A session already exists for this user (' . $user->login . ')');
  286. /*
  287. if ($sess->ip != $userip)
  288. return $this->error(get_string('ws_ipadressmismatch', 'local_wspp',$userip."!=".$sess->ip));
  289. */
  290. //give him more time
  291. ws_set_field('webservices_sessions','sessionbegin',time(),'id',$sess->id);
  292. // V1.6 reuse current session
  293. } else {
  294. $this->debug_output('nouvelle session ');
  295. /// Login valid, create a new session record for this client.
  296. $sess = new stdClass;
  297. $sess->userid = $user->id;
  298. $sess->verified = true;
  299. $sess->ip = $userip;
  300. $sess->sessionbegin = time();
  301. $sess->sessionend = 0;
  302. $sess->sessionkey = $this->add_session_key();
  303. if ($sess->id = ws_insert_record('webservices_sessions', $sess)) {
  304. if ($CFG->ws_logoperations)
  305. add_to_log(SITEID, 'webservice', 'webservice pp', '', __FUNCTION__);
  306. } else
  307. return $this->error(get_string('ws_errorregistersession','local_wspp'));
  308. }
  309. /// Return standard data to be converted into the appropriate data format
  310. /// for return to the client.
  311. $ret = array (
  312. 'client' => $sess->id,
  313. 'sessionkey' => $sess->sessionkey
  314. );
  315. $this->debug_output(print_r($ret, true));
  316. return $ret;
  317. }
  318. /**
  319. * Logs a client out of the system by removing the valid flag from their
  320. * session record and any user ID that is assosciated with their particular
  321. * session.
  322. *
  323. * @param integer $client The client record ID.
  324. * @param string $sesskey The client session key.
  325. * @return boolean True if successfully logged out, false otherwise.
  326. * since this operation retunr s a simple type, no need to override it in protocol specific layer
  327. */
  328. function logout($client, $sesskey) {
  329. global $CFG;
  330. if (!$this->validate_client($client, $sesskey, __FUNCTION__)) {
  331. return $this->error(get_string('ws_invalidclient', 'local_wspp'));
  332. }
  333. if ($sess = ws_get_record('webservices_sessions', 'id', $client, 'sessionend', 0, 'verified', 1)) {
  334. $sess->verified = 0;
  335. $sess->sessionend = time();
  336. if (ws_update_record('webservices_sessions', $sess)) {
  337. return true;
  338. } else {
  339. return false;
  340. }
  341. }
  342. return false;
  343. }
  344. function get_version($client, $sesskey) {
  345. global $CFG;
  346. if (!$this->validate_client($client, $sesskey, __FUNCTION__)) {
  347. return -1; //invalid Moodle's ID
  348. }
  349. return $this->version;
  350. }
  351. /**
  352. * Find and return a list of user records.
  353. *
  354. * @param int $client The client session ID.
  355. * @param string $sesskey The client session key.
  356. * @param array $userids An array of input user values. If empty, return all users
  357. * @param string $idfield The field used to compare the user ID fields against.
  358. * @return array Return data (user record) to be converted into a
  359. * specific data format for sending to the client.
  360. */
  361. function get_users($client, $sesskey, $userids, $idfield = 'idnumber') {
  362. global $USER;
  363. if (!$this->validate_client($client, $sesskey, __FUNCTION__)) {
  364. return $this->error(get_string('ws_invalidclient', 'local_wspp'));
  365. }
  366. /// Verify that the user for this session can perform this operation.
  367. //nothing to check user database is public ?
  368. $ret = array (); // Return array.
  369. if (empty ($userids)) { // all users ...
  370. return filter_users($client, get_users(true), 0);
  371. }
  372. foreach ($userids as $userid) {
  373. $users = ws_get_records('user', $idfield, $userid); //may have more than one !
  374. if (empty ($users)) {
  375. $a = new StdClass();
  376. $a->critere = $idfield;
  377. $a->valeur = $userid;
  378. $ret[] = $this->non_fatal_error(get_string('ws_nomatch', 'local_wspp', $a));
  379. } else {
  380. $ret = array_merge($ret, $users);
  381. }
  382. }
  383. //$this->debug_output("GU" . print_r($ret, true));
  384. return filter_users($client, $ret, 0);
  385. }
  386. /**
  387. * Find and return a list of course records.
  388. *
  389. * @param int $client The client session ID.
  390. * @param string $sesskey The client session key.
  391. * @param array $courseids An array of input course values to search for.If empty, all courses
  392. * @param string $idfield searched column . May be any column of table mdl_course
  393. * @return array Return data (course record) to be converted into a specific
  394. * data format for sending to the client.
  395. */
  396. function get_courses($client, $sesskey, $courseids, $idfield = 'idnumber') {
  397. global $USER;
  398. if (!$this->validate_client($client, $sesskey, __FUNCTION__)) {
  399. return $this->error(get_string('ws_invalidclient', 'local_wspp'));
  400. }
  401. $ret = array ();
  402. if (empty ($courseids)) {
  403. // all courses wanted
  404. $res = ws_get_records('course', '', '');
  405. return filter_courses($client, $res);
  406. }
  407. foreach ($courseids as $courseid) {
  408. if ($courses = ws_get_records('course', $idfield, $courseid)) { //may have more than one
  409. $ret = array_merge($ret, $courses);
  410. } else {
  411. $a = new StdClass();
  412. $a->critere = $idfield;
  413. $a->valeur = $courseid;
  414. $ret[] = $this->non_fatal_error(get_string('ws_nomatch', 'local_wspp', $a));
  415. }
  416. }
  417. return filter_courses($client,$ret);
  418. }
  419. function get_courses_search($client, $sesskey, $search) {
  420. global $USER;
  421. if (!$this->validate_client($client, $sesskey, __FUNCTION__)) {
  422. return $this->error(get_string('ws_invalidclient', 'local_wspp'));
  423. }
  424. $search = trim(strip_tags($search)); // trim & clean raw searched string
  425. if (empty ($search)) {
  426. // all courses wanted
  427. $res = ws_get_records('course', '', '');
  428. return filter_courses($client, $res);
  429. }
  430. $searchterms = explode(" ", $search); // Search for words independently
  431. foreach ($searchterms as $key => $searchterm) {
  432. if (strlen($searchterm) < 2) {
  433. unset($searchterms[$key]);
  434. }
  435. }
  436. $totalcount=0;
  437. $ret = get_courses_search($searchterms, "fullname ASC",0,9999,$totalcount);
  438. return filter_courses($client,$ret);
  439. }
  440. /**
  441. * Find and return a list of resources within one or several courses.
  442. * OK PP tested with php5 5 and python clients
  443. * @param int $client The client session ID.
  444. * @param string $sesskey The client session key.
  445. * @param array $courseids An array of input course id values to search for. If empty return all ressources
  446. * @param string $idfield : the field used to identify courses
  447. * @return array An array of records.
  448. */
  449. function get_resources($client, $sesskey, $courseids, $idfield = 'idnumber') {
  450. global $CFG, $USER;
  451. if (!$this->validate_client($client, $sesskey,__FUNCTION__)) {
  452. return $this->error(get_string('ws_invalidclient', 'local_wspp'));
  453. }
  454. $ret = array ();
  455. if (empty ($courseids)) {
  456. $courses = ws_get_my_courses($USER->id);
  457. } else {
  458. $courses = array ();
  459. foreach ($courseids as $courseid) {
  460. if ($course = ws_get_record('course', $idfield, $courseid))
  461. $courses[] = $course;
  462. else {
  463. //append an error record to the list
  464. $a = new StdClass();
  465. $a->critere = $idfield;
  466. $a->valeur = $courseid;
  467. $ret[] = $this->non_fatal_error(get_string('ws_nomatch', 'local_wspp', $a));
  468. }
  469. }
  470. }
  471. //remove courses not available to current user
  472. $courses = filter_courses($client, $courses);
  473. $ilink = "{$CFG->wwwroot}/mod/resource/view.php?id=";
  474. foreach ($courses as $course) {
  475. if ($resources = get_all_instances_in_course("resource", $course, NULL, true)) {
  476. foreach ($resources as $resource) {
  477. $resource->url = $ilink . $resource->coursemodule;
  478. $ret[] = $resource;
  479. }
  480. }
  481. }
  482. //remove ressources in course where current user is not enroled
  483. return filter_resources($client, $ret);
  484. }
  485. /**
  486. * Find and return a list of sections within one or several courses.
  487. * OK PP tested with php5 5 and python clients
  488. * @param int $client The client session ID.
  489. * @param string $sesskey The client session key.
  490. * @param array $courseids An array of input course id values to search for. If empty return all sections
  491. * @param string $idfield : the field used to identify courses
  492. * @return array An array of course records.
  493. */
  494. public function get_sections($client, $sesskey, $courseids, $idfield = 'idnumber') {
  495. global $CFG, $USER;
  496. if (!$this->validate_client($client, $sesskey,__FUNCTION__)) {
  497. return $this->error(get_string('ws_invalidclient', 'local_wspp'));
  498. }
  499. $ret = array ();
  500. if (empty ($courseids)) {
  501. $courses = ws_get_my_courses($USER->id);
  502. } else {
  503. $courses = array ();
  504. foreach ($courseids as $courseid) {
  505. if ($course = ws_get_record('course', $idfield, $courseid))
  506. $courses[] = $course;
  507. else {
  508. //append an error record to the list
  509. $a = new StdClass();
  510. $a->critere = $idfield;
  511. $a->valeur = $courseid;
  512. $ret[] = $this->non_fatal_error(get_string('ws_nomatch', 'local_wspp', $a));
  513. }
  514. }
  515. }
  516. //remove courses not available to current user
  517. $courses = filter_courses($client, $courses);
  518. foreach ($courses as $course) {
  519. if ($CFG->wspp_using_moodle20)
  520. require_once ($CFG->dirroot.'/course/lib.php');
  521. if ($resources = get_all_sections($course->id))
  522. foreach ($resources as $resource) {
  523. $ret[] = $resource;
  524. }
  525. }
  526. //remove ressources in course where current user is not enroled
  527. return filter_sections($client, $ret);
  528. }
  529. public function get_instances_bytype($client, $sesskey, $courseids, $idfield = 'idnumber', $type) {
  530. //TODO merge with get_resources by giving $type="resource"
  531. global $CFG, $USER;
  532. if (!$this->validate_client($client, $sesskey, __FUNCTION__)) {
  533. return $this->error(get_string('ws_invalidclient', 'local_wspp'));
  534. }
  535. if (empty($type)) {
  536. return $this->error(get_string('ws_emptyparameter', 'local_wspp','type'));
  537. }
  538. $ret = array ();
  539. if (empty ($courseids)) {
  540. $courses = ws_get_my_courses($USER->id);
  541. } else {
  542. $courses = array ();
  543. foreach ($courseids as $courseid) {
  544. if ($course = ws_get_record('course', $idfield, $courseid))
  545. $courses[] = $course;
  546. else {
  547. //append an error record to the list
  548. $a = new StdClass();
  549. $a->critere = $idfield;
  550. $a->valeur = $courseid;
  551. $ret[] = $this->non_fatal_error(get_string('ws_nomatch', 'local_wspp', $a));
  552. }
  553. }
  554. }
  555. //remove courses not available to current user
  556. $courses = filter_courses($client, $courses);
  557. foreach ($courses as $course) {
  558. if (!$resources = get_all_instances_in_course($type, $course, NULL, true)) {
  559. //append an error record to the list
  560. $a = new StdClass();
  561. $a->critere = 'type';
  562. $a->valeur = $type;
  563. $ret[] = $this->non_fatal_error(get_string('ws_nomatch', 'local_wspp', $a));
  564. }else {
  565. $ilink = "{$CFG->wwwroot}/mod/$type/view.php?id=";
  566. foreach ($resources as $resource) {
  567. $resource->url = $ilink . $resource->coursemodule;
  568. $ret[] = $resource;
  569. }
  570. }
  571. }
  572. //remove ressources in course where current user is not enroled
  573. return filter_resources($client, $ret);
  574. }
  575. /**
  576. * Find and return student grades for currently enrolled courses Function for Moodle 1.9)
  577. *
  578. * @uses $CFG
  579. * @param int $client The client session ID.
  580. * @param string $sesskey The client session key.
  581. * @param string $userid The unique id of the student.
  582. * @param string $useridfield The field used to identify the student.
  583. * @param string $courseids Array of courses ids
  584. * @param string $idfield field used for course's ids (idnumber, shortname, id ...)
  585. * @return userGrade [] The student grades
  586. *
  587. */
  588. function get_grades($client, $sesskey, $userid, $useridfield = 'idnumber', $courseids, $courseidfield = 'idnumber') {
  589. global $CFG;
  590. if (!$this->validate_client($client, $sesskey, __FUNCTION__)) {
  591. return $this->error(get_string('ws_invalidclient', 'local_wspp'));
  592. }
  593. if (empty ($courseids))
  594. return server :: get_user_grades($client, $sesskey, $userid, $useridfield);
  595. if (!$this->using19)
  596. return $this->error(get_string(' ws_notsupportedgradebook', 'local_wspp'));
  597. require_once ($CFG->dirroot . '/grade/lib.php');
  598. require_once ($CFG->dirroot . '/grade/querylib.php');
  599. if (!$user = ws_get_record('user', $useridfield, $userid)) {
  600. return $this->error(get_string('ws_userunknown','local_wspp',$userid));
  601. }
  602. $return = array ();
  603. /// Find grade data for the requested IDs.
  604. foreach ($courseids as $cid) {
  605. $rgrade = new stdClass;
  606. /// Get the student grades for each course requested.
  607. if ($course = ws_get_record('course', $courseidfield, $cid)) {
  608. if ($this->has_capability('moodle/grade:viewall', CONTEXT_COURSE, $course->id)) {
  609. // get the floating point final grade
  610. if ($legrade = grade_get_course_grade($user->id, $course->id)) {
  611. $rgrade = $legrade;
  612. $rgrade->error = '';
  613. $rgrade->itemid = $cid;
  614. } else {
  615. $a=new StdClass();
  616. $a->user=fullname($user);
  617. $a->course= $course->fullname;
  618. $rgrade->error = get_string('ws_nogrades','local_wspp',$a);
  619. }
  620. } else {
  621. $rgrade->error= get_string('ws_noseegrades','local_wspp',$course->fullname);
  622. }
  623. } else {
  624. $rgrade->error = get_string('ws_courseunknown','local_wspp', $cid);
  625. }
  626. $return[] = $rgrade;
  627. }
  628. //$this->debug_output("GG".print_r($return, true));
  629. return filter_grades($client, $return);
  630. }
  631. /**
  632. * return user's grade in all courses
  633. * @use get_grades by first creating an array of courses Moodle's ids
  634. */
  635. public function get_user_grades($client, $sesskey, $userid, $idfield = "idnumber") {
  636. if (!$this->validate_client($client, $sesskey, __FUNCTION__)) {
  637. return $this->error(get_string('ws_invalidclient', 'local_wspp'));
  638. }
  639. if (!$this->using19)
  640. return $this->error(get_string(' ws_notsupportedgradebook', 'local_wspp'));
  641. if (!$user = ws_get_record('user', $idfield, $userid)) {
  642. return $this->error(get_string('ws_userunknown','local_wspp',$idfield.'='.$userid));
  643. }
  644. // we cannot call API grade_get_course_grade($user->id) since it does not set the courseid as we want it
  645. if (!$courses = ws_get_my_courses($user->id, $sort = 'sortorder ASC', $fields = 'idnumber')) {
  646. return $this->error(get_string('ws_nocourseforuser','local_wspp',$userid));
  647. }
  648. $courseids = array ();
  649. foreach ($courses as $c)
  650. if (!empty ($c->idnumber))
  651. $courseids[] = $c->idnumber;
  652. //$this->debug_output("GUG=" . print_r($courseids, true));
  653. if (empty ($courseids))
  654. return $this->error(get_string('ws_nocoursewithidnumberforuser','local_wspp', $userid));
  655. // caution not $this->get_user_grades THAT WILL call mdl_sopaserver::get_grades
  656. // resulting in two calls of to_soaparray !!!!
  657. return server :: get_grades($client, $sesskey, $userid, $idfield, $courseids, 'idnumber');
  658. }
  659. public function get_course_grades($client, $sesskey, $courseid, $idfield = "idnumber") {
  660. global $CFG, $USER;
  661. if (!$this->validate_client($client, $sesskey, __FUNCTION__)) {
  662. return $this->error(get_string('ws_invalidclient', 'local_wspp'));
  663. }
  664. if (!$this->using19)
  665. return $this->error(get_string(' ws_notsupportedgradebook', 'local_wspp'));
  666. require_once ($CFG->dirroot . '/grade/lib.php');
  667. require_once ($CFG->dirroot . '/grade/querylib.php');
  668. $return = array ();
  669. //Get all student grades for course requested.
  670. if ($course = ws_get_record('course', $idfield, $courseid)) {
  671. $context = get_context_instance(CONTEXT_COURSE, $course->id);
  672. if (has_capability('moodle/grade:viewall', $context)) {
  673. $students = array ();
  674. $students = get_role_users(5, $context, true, '');
  675. //$this->debug_output("GcG".print_r($students, true));
  676. foreach ($students as $user) {
  677. if ($legrade = grade_get_course_grade($user->id, $course->id)) {
  678. $rgrade = $legrade;
  679. $rgrade->error = '';
  680. $rgrade->itemid = $user->idnumber;
  681. // $this->debug_output("IDS=".print_r($legrade,true));
  682. $return[] = $rgrade;
  683. } else {
  684. $a=new StdClass();
  685. $a->user=fullname($user);
  686. $a->course= $course->fullname;
  687. $rgrade=new StdClass();
  688. $rgrade->error = get_string('ws_nogrades','local_wspp',$a);
  689. $return[] = $rgrade;
  690. }
  691. }
  692. } else {
  693. $rgrade=new StdClass();
  694. $rgrade->error = get_string('ws_noseegrades','local_wspp',$course->fullname);
  695. $return[] = $rgrade;
  696. }
  697. } else {
  698. $rgrade=new StdClass();
  699. $rgrade->error = get_string('ws_courseunknown','local_wspp', $courseid);
  700. $return[] = $rgrade;
  701. }
  702. //$this->debug_output("GcG".print_r($return, true));
  703. return filter_grades($client, $return);
  704. }
  705. /**
  706. * determine the primary role of user in a course
  707. * @param int $client The client session record ID.
  708. * @param string $sesskey The session key returned by a previous login.
  709. * @param string userid
  710. * @param string useridfield
  711. * @param string courseid
  712. * @param string courseidfield
  713. * @return integer
  714. * 1 admin
  715. * 2 coursecreator
  716. * 3 editing teacher
  717. * 4 non editing teacher
  718. * 5 student
  719. * 6 guest IF course allows guest AND username ==guest
  720. * 0 nothing
  721. * since this operation retunr s a simple type, no need to override it in protocol specific layer
  722. */
  723. function get_primaryrole_incourse($client, $sesskey, $userid, $useridfield, $courseid, $courseidfield) {
  724. if (!$this->validate_client($client, $sesskey, __FUNCTION__)) {
  725. return $this->error(get_string('ws_invalidclient', 'local_wspp'));
  726. }
  727. // convert user request criteria to an userid
  728. $user = ws_get_record('user', $useridfield, $userid);
  729. if (!$user)
  730. return $this->error(get_string('ws_userunknown','local_wspp',$useridfield."=".$userid));
  731. $userid = $user->id;
  732. // convert course request criteria to a courseid
  733. $course = ws_get_record('course', $courseidfield, $courseid);
  734. if (!$course)
  735. return $this->error(get_string('ws_courseunknown','local_wspp',$courseidfield."=".$courseid ));
  736. return ws_get_primaryrole_incourse($course, $userid);
  737. }
  738. /**
  739. * determine if user has (at least) a given role in a course
  740. * @param int $client The client session record ID.
  741. * @param string $sesskey The session key returned by a previous login.
  742. * @param string userid
  743. * @param string useridfield
  744. * @param string courseid
  745. * @param string courseidfield
  746. * @param int roleid
  747. * @return boolean True if Ok , False otherwise.
  748. * since this operation retunr s a simple type, no need to override it in protocol specific layer
  749. */
  750. function has_role_incourse($client, $sesskey, $userid, $useridfield, $courseid, $courseidfield, $roleid) {
  751. $tmp = server :: get_primaryrole_incourse($client, $sesskey, $userid, $useridfield, $courseid, $courseidfield);
  752. return ($tmp <= $roleid);
  753. }
  754. /**
  755. * Find and return a list of courses that a user is a member of.
  756. *
  757. * @param int $client The client session ID.
  758. * @param string $sesskey The client session key.
  759. * @param string $uinfo (optional) Moodle's id of user. If absent, uses current session user id
  760. * @param string $idfield (default ='id', ignored if $uinfo is empty)
  761. * @param string $sort requested order . Default fullname as per rev 1.5.11
  762. * @return array Return data (course record) to be converted into a specific
  763. * data format for sending to the client.
  764. */
  765. function get_my_courses($client, $sesskey, $uinfo = '', $idfield = 'id', $sort = '') {
  766. global $CFG,$USER;
  767. if (!$this->validate_client($client, $sesskey, __FUNCTION__)) {
  768. return $this->error(get_string('ws_invalidclient', 'local_wspp')." ".__FUNCTION__);
  769. }
  770. $cuid = $USER->id;
  771. if (!empty($uinfo)) {
  772. // find userid if not current user
  773. if (!$user = ws_get_record('user', $idfield, $uinfo))
  774. return $this->error(get_string('ws_userunknown','local_wspp',idfield."=".$uinfo));
  775. $uid=$user->id;
  776. } else
  777. $uid = $cuid; //use current user and ignore $idfield
  778. //only admin user can request courses for others
  779. if ($uid != $cuid) {
  780. if (!$this->has_capability('moodle/user:loginas', CONTEXT_SYSTEM, 0)) {
  781. return $this->error(get_string('ws_operationnotallowed','local_wspp'));
  782. }
  783. }
  784. $sort = $sort ? $sort : 'fullname';
  785. if (isguestuser($user))
  786. $res = ws_get_records('course', 'guest', 1, $sort);
  787. else {
  788. //Moodle 1.95 do not return all fields set in wsdl
  789. if (!$CFG->wspp_using_moodle20)
  790. $extrafields="password,summary,format,showgrades,newsitems,enrolperiod,numsections,marker,maxbytes,
  791. hiddensections,lang,theme,cost,timecreated,timemodified,metacourse";
  792. else
  793. // some fields are not anymore defined in Moodle 2.0
  794. $extrafields="summary,format,showgrades,newsitems,numsections,marker,maxbytes,
  795. hiddensections,lang,theme,timecreated,timemodified";
  796. $res = ws_get_my_courses($uid, $sort,$extrafields);
  797. }
  798. if ($res) {
  799. //rev 1.6 return primary role for each course
  800. foreach ($res as $id=>$value)
  801. $res[$id]->myrole= ws_get_primaryrole_incourse($res[$id],$uid);
  802. //return $res;
  803. return filter_courses($client, $res);
  804. }
  805. else
  806. return $this->non_fatal_error(get_string('ws_nothingfound','local_wspp'));
  807. }
  808. /**
  809. * returns users having $idrole in course identified by $idcourse
  810. * @param string $idcourse unique identifierr of course
  811. * @param string $idfield name of field used to finc course (idnumber, id, shortname), should be unique
  812. * @param integer $idrole role searched for (0 = any role)
  813. */
  814. function get_users_bycourse($client, $sesskey, $idcourse, $idfield, $idrole = 0) {
  815. global $USER;
  816. if (!$this->validate_client($client, $sesskey, __FUNCTION__)) {
  817. return $this->error(get_string('ws_invalidclient', 'local_wspp'));
  818. }
  819. if (!$course = ws_get_record('course', $idfield, $idcourse)) {
  820. return $this->error(get_string('ws_courseunknown','local_wspp',$idfield."=".$idcourse ));
  821. }
  822. if (!$this->has_capability('moodle/course:update', CONTEXT_COURSE, $course->id)
  823. && !ws_is_enrolled($course->id,$USER->id))
  824. return $this->error(get_string('ws_operationnotallowed','local_wspp'));
  825. if (!empty ($roleid) && !ws_record_exists('role', 'id', $idrole))
  826. return $this->error(get_string('ws_roleunknown','local_wspp',$idrole ));
  827. $context = get_context_instance(CONTEXT_COURSE, $course->id);
  828. if ($res = get_role_users($idrole, $context, true, '')) {
  829. //rev 1.6 if $idrole is empty return primary role for each user
  830. if (empty($idrole)) {
  831. foreach ($res as $id=>$value)
  832. $res[$id]->role=ws_get_primaryrole_incourse($course,$res[$id]->id);
  833. }
  834. return filter_users($client, $res, $idrole);
  835. } else {
  836. return $this->non_fatal_error(get_string('ws_nothingfound','local_wspp'));
  837. }
  838. }
  839. function get_roles($client, $sesskey, $roleid = '', $idfield = '') {
  840. if (!$this->validate_client($client, $sesskey, __FUNCTION__)) {
  841. return $this->error(get_string('ws_invalidclient', 'local_wspp'));
  842. }
  843. // Get a list of all the roles in the database, sorted by their short names.
  844. if ($res = ws_get_records('role', $idfield, $roleid, 'shortname, id', '*')) {
  845. return $res;
  846. } else {
  847. return $this->non_fatal_error(get_string('ws_nothingfound','local_wspp'));
  848. }
  849. }
  850. function get_categories($client, $sesskey, $catid = '', $idfield = '') {
  851. if (!$this->validate_client($client, $sesskey,__FUNCTION__)) {
  852. return $this->error(get_string('ws_invalidclient', 'local_wspp'));
  853. }
  854. $ret = array ();
  855. // Get a list of all the categories in the database, sorted by their name
  856. if ($res = ws_get_records('course_categories', $idfield, $catid, 'name', '*')) {
  857. return filter_categories($client, $res);
  858. } else {
  859. return $this->non_fatal_error(get_string('ws_nothingfound','local_wspp'));
  860. }
  861. }
  862. function get_events($client, $sesskey, $eventtype, $ownerid,$owneridfield='id') {
  863. global $USER;
  864. if (!$this->validate_client($client, $sesskey, __FUNCTION__)) {
  865. return $this->error(get_string('ws_invalidclient', 'local_wspp'));
  866. }
  867. $ret = array ();
  868. // Get a list of all the events in the database, sorted by their short names.
  869. //TODO filter by eventype ...
  870. switch ($eventtype) {
  871. case cal_show_global :
  872. $idfield = 'courseid';
  873. $ownerid = 1;
  874. break;
  875. case cal_show_course :
  876. $idfield = 'courseid';
  877. if (!$course =ws_get_record('course',$owneridfield,$ownerid)) {
  878. return $this->error(get_string('ws_courseunknown','local_wspp',$owneridfield."=".$ownerid ));
  879. }
  880. $ownerid=$course->id;
  881. break;
  882. case cal_show_group :
  883. $idfield = 'groupid';
  884. if (!$group =ws_get_record('groups',$owneridfield,$ownerid)) {
  885. return $this->error(get_string('ws_groupunknown','local_wspp',$owneridfield."=".$ownerid ));
  886. }
  887. $ownerid=$group->id;
  888. break;
  889. case cal_show_user :
  890. $idfield = 'userid';
  891. if (!$user =ws_get_record('user',$owneridfield,$ownerid)) {
  892. return $this->error(get_string('ws_userunknown','local_wspp',$owneridfield."=".$ownerid ));
  893. }
  894. $ownerid=$user->id;
  895. break;
  896. default :
  897. $idfield = '';
  898. $ownerid = '';
  899. }
  900. if ($res = ws_get_records('event', $idfield, $ownerid)) {
  901. foreach ($res as $r) {
  902. $r = filter_event($client, $eventtype, $r);
  903. if ($r)
  904. $ret[] = $r;
  905. }
  906. } else {
  907. $ret[]=$this->non_fatal_error(get_string('ws_nothingfound','local_wspp'));
  908. }
  909. return $ret;
  910. }
  911. function get_group_members($client, $sesskey, $groupid,$groupidfield='id') {
  912. global $USER;
  913. if (!$this->validate_client($client, $sesskey, __FUNCTION__)) {
  914. return $this->error(get_string('ws_invalidclient', 'local_wspp'));
  915. }
  916. if (!$group = ws_get_record('groups', $groupidfield, $groupid)) {
  917. return $this->error(get_string('ws_groupunknown','local_wspp',$groupid));
  918. }
  919. if (!$this->has_capability('moodle/course:update', CONTEXT_COURSE, $group->courseid)
  920. && ! ws_is_enrolled($group->courseid,$USER->id))
  921. return $this->error(get_string('ws_operationnotallowed','local_wspp'));
  922. //$res = get_group_users($group->id); deprecated Moodle 1.9 removed Moodle 2.0
  923. $res=groups_get_members($group->id);
  924. if (!$res)
  925. return $this->non_fatal_error(get_string('ws_nothingfound','local_wspp'));
  926. return filter_users($client, $res, 0);
  927. }
  928. function get_grouping_members($client, $sesskey, $groupid,$groupidfield='id') {
  929. global $USER;
  930. if (!$this->validate_client($client, $sesskey, __FUNCTION__)) {
  931. return $this->error(get_string('ws_invalidclient', 'local_wspp'));
  932. }
  933. if (!$group = ws_get_record('groupings', $groupidfield, $groupid)) {
  934. return $this->error(get_string('ws_groupingunknown','local_wspp',$groupid));
  935. }
  936. if (!$this->has_capability('moodle/course:update', CONTEXT_COURSE, $group->courseid)
  937. && ! ws_is_enrolled($group->courseid,$USER->id))
  938. return $this->error(get_string('ws_operationnotallowed','local_wspp'));
  939. $res = groups_get_grouping_members($group->id);
  940. if (!$res)
  941. return $this->non_fatal_error(get_string('ws_nothingfound','local_wspp'));
  942. return filter_users($client, $res, 0);
  943. }
  944. function get_cohort_members($client, $sesskey, $groupid,$groupidfield='id') {
  945. global $DB,$CFG;
  946. if (!$CFG->wspp_using_moodle20)
  947. return $this->error(get_string('ws_moodle20only', 'local_wspp'));
  948. if (!$this->validate_client($client, $sesskey, __FUNCTION__)) {
  949. return $this->error(get_string('ws_invalidclient', 'local_wspp'));
  950. }
  951. if (!$group = ws_get_record('cohort', $groupidfield, $groupid)) {
  952. return $this->error(get_string('ws_cohortunknown','local_wspp',$groupid));
  953. }
  954. /*
  955. if (!$this->has_capability('moodle/cohort:update', CONTEXT_COURSECAT, $group->contextid))
  956. return $this->error(get_string('ws_operationnotallowed','local_wspp'));
  957. */
  958. $params['cohortid'] = $group->id;
  959. $fields = 'SELECT u.*';
  960. $sql = " FROM {user} u
  961. JOIN {cohort_members} cm ON (cm.userid = u.id AND cm.cohortid = :cohortid)";
  962. try {
  963. $res = $DB->get_records_sql($fields . $sql, $params);
  964. if (!$res)
  965. return $this->non_fatal_error(get_string('ws_nothingfound','local_wspp'));
  966. } catch (Exception $e) {
  967. ws_error_log($e);
  968. }
  969. return filter_users($client, $res, 0);
  970. }
  971. protected function get_groups($client, $sesskey,$groups,$idfield,$courseid){
  972. if (empty($groups) && $courseid) {
  973. return server::get_groups_bycourse ($client,$sesskey,$courseid);
  974. }
  975. if (!$this->validate_client($client, $sesskey, __FUNCTION__)) {
  976. return $this->error(get_string('ws_invalidclient', 'local_wspp'));
  977. }
  978. global $CFG;
  979. $ret = array();
  980. if ($courseid) {
  981. $courseselect = 'AND g.courseid ='.$courseid ;
  982. } else {
  983. $courselect = '';
  984. }
  985. // $this->debug_output("groupes=".print_r($groups,true));
  986. foreach ($groups as $group) {
  987. $sql= "$idfield ='$group' $courseselect ";
  988. if ($g = ws_get_records_select('groups',$sql)) {
  989. $g=filter_groups($client,$g);
  990. foreach($g as $one) {
  991. $ret[] = $one;
  992. }
  993. } else {
  994. $ret[]=$this->non_fatal_error(get_string('nogroups','local_wspp')); // "Invalid group $idfield :$group ");
  995. }
  996. }
  997. //$this->debug_output("groupes tr=".print_r($ret,true));
  998. return $ret;
  999. }
  1000. protected function get_groupings($client, $sesskey,$groups,$idfield,$courseid){
  1001. if (empty($groups) && $courseid) {
  1002. return server::get_groupings_bycourse ($client,$sesskey,$courseid);
  1003. }
  1004. if (!$this->validate_client($client, $sesskey, __FUNCTION__)) {
  1005. return $this->error(get_string('ws_invalidclient', 'local_wspp'));
  1006. }
  1007. global $CFG;
  1008. $ret = array();
  1009. if ($courseid) {
  1010. $courseselect = 'AND g.courseid ='.$courseid ;
  1011. } else {
  1012. $courselect = '';
  1013. }
  1014. //$this->debug_output("groupings=".print_r($groups,true));
  1015. foreach ($groups as $group) {
  1016. $sql= "$idfield ='$group' $courseselect ";
  1017. if ($g = ws_get_records_select('groupings',$sql)) {
  1018. $g=filter_groupings($client,$g);
  1019. foreach($g as $one) {
  1020. $ret[] = $one;
  1021. }
  1022. } else {
  1023. $ret[]=$this->non_fatal_error(get_string('nogroupings','local_wspp')); // "Invalid group $idfield :$group ");
  1024. }
  1025. }
  1026. //$this->debug_output("groupings tr=".print_r($ret,true));
  1027. return $ret;
  1028. }
  1029. protected function get_cohorts($client, $sesskey,$groups,$idfield){
  1030. if (empty($groups)) {
  1031. return server::get_all_cohorts($client,$sesskey);
  1032. }
  1033. if (!$this->validate_client($client, $sesskey, __FUNCTION__)) {
  1034. return $this->error(get_string('ws_invalidclient', 'local_wspp'));
  1035. }
  1036. $ret = array();
  1037. foreach ($groups as $group) {
  1038. $sql= "$idfield ='$group' ";
  1039. if ($g = ws_get_records_select('cohort',$sql)) {
  1040. $g=filter_cohorts($client,$g);
  1041. foreach($g as $one) {
  1042. $ret[] = $one;
  1043. }
  1044. } else {
  1045. $ret[]=$this->non_fatal_error(get_string('nocohorts','local_wspp')); // "Invalid group $idfield :$group ");
  1046. }
  1047. }
  1048. //$this->debug_output("cohorts tr=".print_r($ret,true));
  1049. return $ret;
  1050. }
  1051. /**
  1052. * Add user to group
  1053. * @uses $CFG
  1054. * @param int $client The client session ID.
  1055. * @param string $sesskey The client session key.
  1056. * @param int $userid The user's id
  1057. * @param int $groupid The group's id
  1058. * @return affectRecord Return data (affectRecord object) to be converted into a
  1059. * specific data format for sending to the client.
  1060. */
  1061. function affect_user_to_group($client, $sesskey, $userid, $groupid) {
  1062. global $CFG;
  1063. if (!$this->validate_client($client, $sesskey, __FUNCTION__)) {
  1064. return $this->error(get_string('ws_invalidclient', 'local_wspp'));
  1065. }
  1066. if (!$group = ws_get_record('groups', 'id', $groupid)) {
  1067. return $this->error(get_string('ws_groupunknown','local_wspp','id='.$groupid));
  1068. }
  1069. /// Check for correct permissions.
  1070. if (!$this->has_capability('moodle/course:managegroups', CONTEXT_COURSE, $group->courseid)) {
  1071. return $this->error(get_string('ws_operationnotallowed','local_wspp'));
  1072. }
  1073. if (!$user = ws_get_record("user", "id", $userid)) {
  1074. return $this->error(get_string('ws_userunknown','local_wspp','id='.$userid));
  1075. }
  1076. /// Check user is enroled in course
  1077. if (!ws_is_enrolled( $group->courseid, $user->id)) {
  1078. $a=new StdClass();
  1079. $a->user=$user->username;
  1080. $a->course=$group->courseid;
  1081. return $this->error(get_string('ws_user_notenroled','local_wspp',$a));
  1082. }
  1083. if ($CFG->wspp_using_moodle20) {
  1084. // not anymore included by defualt in Moodle 2.0
  1085. require_once ($CFG->dirroot.'/group/lib.php');
  1086. }
  1087. $resp = new stdClass();
  1088. $resp->status = groups_add_member($group->id, $user->id);
  1089. return $resp;
  1090. }
  1091. function remove_user_from_group($client, $sesskey, $userid, $groupid) {
  1092. global $CFG;
  1093. if (!$this->validate_client($client, $sesskey, __FUNCTION__)) {
  1094. return $this->error(get_string('ws_invalidclient', 'local_wspp'));
  1095. }
  1096. if (!$group = ws_get_record('groups', 'id', $groupid)) {
  1097. return $this->error(get_string('ws_groupunknown','local_wspp','id='.$groupid));
  1098. }
  1099. /// Check for correct permissions.
  1100. if (!$this->has_capability('moodle/course:managegroups', CONTEXT_COURSE, $group->courseid)) {
  1101. return $this->error(get_string('ws_operationnotallowed','local_wspp'));
  1102. }
  1103. if (!$user = ws_get_record("user", "id", $userid)) {
  1104. return $this->error(get_string('ws_userunknown','local_wspp','id='.$userid));
  1105. }
  1106. /// Check user is member
  1107. if (!ws_is_enrolled( $group->courseid, $user->id)) {
  1108. $a=new StdClass();
  1109. $a->user=$user->username;
  1110. $a->course=$group->courseid;
  1111. return $this->error(get_string('ws_user_notenroled','local_wspp',$a));
  1112. }
  1113. if ($CFG->wspp_using_moodle20) {
  1114. // not anymore included by defualt in Moodle 2.0
  1115. require_once ($CFG->dirroot.'/group/lib.php');
  1116. }
  1117. $resp = new stdClass();
  1118. $resp->status = groups_remove_member($group->id, $user->id);
  1119. return $resp;
  1120. }
  1121. /**
  1122. * Add user to cohort
  1123. * @uses $CFG
  1124. * @param int $client The client session ID.
  1125. * @param string $sesskey The client session key.
  1126. * @param int $userid The user's id
  1127. * @param int $groupid The group's id
  1128. * @return affectRecord Return data (affectRecord object) to be converted into a
  1129. * specific data format for sending to the client.
  1130. */
  1131. function affect_user_to_cohort($client, $sesskey, $userid, $groupid) {
  1132. global $CFG;
  1133. if (!$this->validate_client($client, $sesskey, __FUNCTION__)) {
  1134. return $this->error(get_string('ws_invalidclient', 'local_wspp'));
  1135. }
  1136. if (!$group = ws_get_record('cohort', 'id', $groupid)) {
  1137. return $this->error(get_string('ws_cohortunknown','local_wspp','id='.$groupid));
  1138. }
  1139. /// Check for correct permissions.
  1140. if (!$this->has_capability('moodle/cohort:manage', CONTEXT_COURSECAT, $group->contextid)) {
  1141. return $this->error(get_string('ws_operationnotallowed','local_wspp'));
  1142. }
  1143. if (!$user = ws_get_record("user", "id", $userid)) {
  1144. return $this->error(get_string('ws_userunknown','local_wspp','id='.$userid));
  1145. }
  1146. if ($CFG->wspp_using_moodle20) {
  1147. require_once ($CFG->dirroot.'/cohort/lib.php');
  1148. }else
  1149. return $this->error(get_string('ws_moodle20only', 'local_wspp'));
  1150. cohort_add_member($group->id,$user->id);
  1151. $resp->status = 1;
  1152. return $resp;
  1153. }
  1154. /**remove user from cohort
  1155. * @uses $CFG
  1156. * @param int $client The client session ID.
  1157. * @param string $sesskey The client session key.
  1158. * @param int $userid The user's id
  1159. * @param int $groupid The group's id
  1160. * @return affectRecord Return data (affectRecord object) to be converted into a
  1161. * specific data format for sending to the client.
  1162. */
  1163. function remove_user_from_cohort($client, $sesskey, $userid, $groupid) {
  1164. global $CFG;
  1165. if (!$this->validate_client($client, $sesskey, __FUNCTION__)) {
  1166. return $this->error(get_string('ws_invalidclient', 'local_wspp'));
  1167. }
  1168. if (!$group = ws_get_record('cohort', 'id', $groupid)) {
  1169. return $this->error(get_string('ws_cohortunknown','local_wspp','id='.$groupid));
  1170. }
  1171. /// Check for correct permissions.
  1172. if (!$this->has_capability('moodle/cohort:manage', CONTEXT_COURSECAT, $group->contextid)) {
  1173. return $this->error(get_string('ws_operationnotallowed','local_wspp'));
  1174. }
  1175. if (!$user = ws_get_record("user", "id", $userid)) {
  1176. return $this->error(get_string('ws_userunknown','local_wspp','id='.$userid));
  1177. }
  1178. if ($CFG->wspp_using_moodle20) {
  1179. require_once ($CFG->dirroot.'/cohort/lib.php');
  1180. }else
  1181. return $this->error(get_string('ws_moodle20only', 'local_wspp'));
  1182. cohort_remove_member($group->id,$user->id);
  1183. $resp->status = 1;
  1184. return $resp;
  1185. }
  1186. function affect_group_to_grouping($client, $sesskey, $groupid, $groupingid) {
  1187. global $CFG;
  1188. if (!$this->validate_client($client, $sesskey, __FUNCTION__)) {
  1189. return $this->error(get_string('ws_invalidclient', 'local_wspp'));
  1190. }
  1191. if (!$group = ws_get_record('groups', 'id', $groupid)) {
  1192. return $this->error(get_string('ws_groupunknown','local_wspp','id='.$groupid));
  1193. }
  1194. if (!$grouping = ws_get_record('groupings', 'id', $groupingid)) {
  1195. return $this->error(get_string('ws_groupingunknown','local_wspp','id='.$groupingid));
  1196. }
  1197. if ($group->courseid != $grouping->courseid) {
  1198. $a=new StdClass();
  1199. $a->group=$group->id;
  1200. $a->grouping=$grouping->id;
  1201. return $this->error(get_string('ws_group_grouping_notsamecourse','local_wspp',$a));
  1202. }
  1203. /// Check for correct permissions.
  1204. if (!$this->has_capability('moodle/course:managegroups', CONTEXT_COURSE, $group->courseid)) {
  1205. return $this->error(get_string('ws_operationnotallowed','local_wspp'));
  1206. }
  1207. if ($CFG->wspp_using_moodle20) {
  1208. // not anymore included by defualt in Moodle 2.0
  1209. require_once ($CFG->dirroot.'/group/lib.php');
  1210. }

Large files files are truncated, but you can click here to view the full file