gradebook.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. use Skill as SkillManager;
  4. require_once __DIR__.'/../inc/global.inc.php';
  5. ini_set('memory_limit', -1);
  6. /*
  7. ini_set('upload_max_filesize', '4000M');
  8. ini_set('post_max_size', '4000M');
  9. ini_set('max_execution_time', '80000');
  10. ini_set('max_input_time', '80000');
  11. */
  12. $debug = true;
  13. define('WS_ERROR_SECRET_KEY', 1);
  14. function return_error($code)
  15. {
  16. $fault = null;
  17. switch ($code) {
  18. case WS_ERROR_SECRET_KEY:
  19. $fault = new soap_fault('Server', '', 'Secret key is not correct or params are not correctly set');
  20. break;
  21. }
  22. return $fault;
  23. }
  24. function WSHelperVerifyKey($params)
  25. {
  26. global $_configuration, $debug;
  27. if (is_array($params)) {
  28. $secret_key = $params['secret_key'];
  29. } else {
  30. $secret_key = $params;
  31. }
  32. //error_log(print_r($params,1));
  33. $check_ip = false;
  34. $ip_matches = false;
  35. $ip = trim($_SERVER['REMOTE_ADDR']);
  36. // if we are behind a reverse proxy, assume it will send the
  37. // HTTP_X_FORWARDED_FOR header and use this IP instead
  38. if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
  39. list($ip1) = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
  40. $ip = trim($ip1);
  41. }
  42. if ($debug) {
  43. error_log("ip: $ip");
  44. }
  45. // Check if a file that limits access from webservices exists and contains
  46. // the restraining check
  47. if (is_file('webservice-auth-ip.conf.php')) {
  48. include 'webservice-auth-ip.conf.php';
  49. if ($debug) {
  50. error_log("webservice-auth-ip.conf.php file included");
  51. }
  52. if (!empty($ws_auth_ip)) {
  53. $check_ip = true;
  54. $ip_matches = api_check_ip_in_range($ip, $ws_auth_ip);
  55. if ($debug) {
  56. error_log("ip_matches: $ip_matches");
  57. }
  58. }
  59. }
  60. if ($debug) {
  61. error_log("checkip ".intval($check_ip));
  62. }
  63. if ($check_ip) {
  64. $security_key = $_configuration['security_key'];
  65. } else {
  66. $security_key = $ip.$_configuration['security_key'];
  67. //error_log($secret_key.'-'.$security_key);
  68. }
  69. $result = api_is_valid_secret_key($secret_key, $security_key);
  70. //error_log($secret_key.'-'.$security_key);
  71. if ($debug) {
  72. error_log('WSHelperVerifyKey result: '.intval($result));
  73. }
  74. return $result;
  75. }
  76. // Create the server instance
  77. $server = new soap_server();
  78. //$server->soap_defencoding = 'UTF-8';
  79. // Initialize WSDL support
  80. $server->configureWSDL('WSGradebook', 'urn:WSGradebook');
  81. $server->wsdl->addComplexType(
  82. 'WSGradebookScoreParams',
  83. 'complexType',
  84. 'struct',
  85. 'all',
  86. '',
  87. [
  88. 'item_id' => [
  89. 'name' => 'item_id',
  90. 'type' => 'xsd:string',
  91. ],
  92. 'item_type' => [
  93. 'name' => 'item_type',
  94. 'type' => 'xsd:string',
  95. ],
  96. 'email' => [
  97. 'name' => 'email',
  98. 'type' => 'xsd:string',
  99. ],
  100. 'secret_key' => ['name' => 'secret_key', 'type' => 'xsd:string'],
  101. ]
  102. );
  103. $server->wsdl->addComplexType(
  104. 'returnItemScore',
  105. 'complexType',
  106. 'struct',
  107. 'sequence',
  108. '',
  109. [
  110. 'score' => ['name' => 'score', 'type' => 'xsd:string'],
  111. 'date' => ['name' => 'date', 'type' => 'xsd:string'],
  112. 'counter' => ['name' => 'counter', 'type' => 'xsd:string'],
  113. ]
  114. );
  115. // Register the method to expose
  116. $server->register(
  117. 'WSGetGradebookUserItemScore', // method name
  118. ['params' => 'tns:WSGradebookScoreParams'], // input parameters
  119. ['return' => 'tns:returnItemScore'], // output parameters
  120. 'urn:WSGradebook', // namespace
  121. 'urn:WSGradebook#WSGetGradebookUserItemScore', // soapaction
  122. 'rpc', // style
  123. 'encoded', // use
  124. 'get gradebook item user result'
  125. );
  126. /**
  127. * @param array $params
  128. *
  129. * @return int|string
  130. */
  131. function WSGetGradebookUserItemScore($params)
  132. {
  133. if (!WSHelperVerifyKey($params)) {
  134. return return_error(WS_ERROR_SECRET_KEY);
  135. }
  136. $itemId = $params['item_id'];
  137. $itemType = $params['item_type'];
  138. $email = $params['email'];
  139. $userInfo = api_get_user_info_from_email($email);
  140. if (empty($userInfo)) {
  141. return new soap_fault('Server', '', 'User not found');
  142. }
  143. $em = Database::getManager();
  144. $score = [];
  145. switch ($itemType) {
  146. case 'link':
  147. /** @var \Chamilo\CoreBundle\Entity\GradebookLink $link */
  148. $link = $em->getRepository('ChamiloCoreBundle:GradebookLink')->find($itemId);
  149. if (empty($link)) {
  150. return new soap_fault('Server', '', 'gradebook link not found');
  151. }
  152. $links = AbstractLink::load($link->getId());
  153. switch ($link->getType()) {
  154. case LINK_EXERCISE:
  155. /** @var ExerciseLink $link */
  156. foreach ($links as $link) {
  157. $link->set_session_id($link->getCategory()->get_session_id());
  158. $score = $link->calc_score($userInfo['user_id']);
  159. break;
  160. }
  161. break;
  162. case LINK_STUDENTPUBLICATION:
  163. /** @var StudentPublicationLink $link */
  164. foreach ($links as $link) {
  165. $link->set_session_id($link->getCategory()->get_session_id());
  166. $score = $link->calc_score($userInfo['user_id']);
  167. break;
  168. }
  169. break;
  170. }
  171. break;
  172. case 'evaluation':
  173. //$evaluation = $em->getRepository('ChamiloCoreBundle:GradebookEvaluation')->find($itemId);
  174. break;
  175. }
  176. if (!empty($score)) {
  177. $result = ExerciseLib::show_score($score[0], $score[1], false);
  178. $result = strip_tags($result);
  179. return ['score' => $result, 'date' => $score[2], 'counter' => $score[3]];
  180. }
  181. return new soap_fault('Server', '', 'Score not found');
  182. }
  183. $server->wsdl->addComplexType(
  184. 'WSGradebookCategoryScoreParams',
  185. 'complexType',
  186. 'struct',
  187. 'all',
  188. '',
  189. [
  190. 'course_code' => [
  191. 'name' => 'course_code',
  192. 'type' => 'xsd:string',
  193. ],
  194. 'session_id' => [
  195. 'name' => 'session_id',
  196. 'type' => 'xsd:string',
  197. ],
  198. 'email' => [
  199. 'name' => 'email',
  200. 'type' => 'xsd:string',
  201. ],
  202. 'secret_key' => ['name' => 'secret_key', 'type' => 'xsd:string'],
  203. ]
  204. );
  205. // Register the method to expose
  206. $server->register(
  207. 'WSGetGradebookCategoryUserScore', // method name
  208. ['params' => 'tns:WSGradebookCategoryScoreParams'], // input parameters
  209. ['return' => 'xsd:string'], // output parameters
  210. 'urn:WSGradebook', // namespace
  211. 'urn:WSGradebook#WSGetGradebookCategoryUserScore', // soapaction
  212. 'rpc', // style
  213. 'encoded'
  214. );
  215. /**
  216. * @param array $params
  217. *
  218. * @return int|string
  219. */
  220. function WSGetGradebookCategoryUserScore($params)
  221. {
  222. if (!WSHelperVerifyKey($params)) {
  223. return return_error(WS_ERROR_SECRET_KEY);
  224. }
  225. $courseCode = $params['course_code'];
  226. $sessionId = (int) $params['session_id'];
  227. if (!empty($sessionId)) {
  228. $sessionInfo = api_get_session_info($sessionId);
  229. if (empty($sessionInfo)) {
  230. return new soap_fault('Server', '', 'Session not found');
  231. }
  232. }
  233. $email = $params['email'];
  234. $userInfo = api_get_user_info_from_email($email);
  235. if (empty($userInfo)) {
  236. return new soap_fault('Server', '', 'User not found');
  237. }
  238. $userId = $userInfo['user_id'];
  239. $courseInfo = api_get_course_info($courseCode);
  240. if (empty($courseInfo)) {
  241. return new soap_fault('Server', '', 'Course not found');
  242. }
  243. $cats = Category::load(null,
  244. null,
  245. $courseCode,
  246. null,
  247. null,
  248. $sessionId
  249. );
  250. /** @var Category $category */
  251. $category = isset($cats[0]) ? $cats[0] : null;
  252. $scorecourse_display = null;
  253. if (!empty($category)) {
  254. $categoryCourse = Category::load($category->get_id());
  255. $category = isset($categoryCourse[0]) ? $categoryCourse[0] : null;
  256. $allevals = $category->get_evaluations($userId, true);
  257. $alllinks = $category->get_links($userId, true);
  258. $allEvalsLinks = array_merge($allevals, $alllinks);
  259. $main_weight = $category->get_weight();
  260. $scoredisplay = ScoreDisplay::instance();
  261. $item_value_total = 0;
  262. /** @var AbstractLink $item */
  263. foreach ($allEvalsLinks as $item) {
  264. $item->set_session_id($sessionId);
  265. $item->set_course_code($courseCode);
  266. $score = $item->calc_score($userId);
  267. if (!empty($score)) {
  268. $divide = $score[1] == 0 ? 1 : $score[1];
  269. $item_value = $score[0] / $divide * $item->get_weight();
  270. $item_value_total += $item_value;
  271. }
  272. }
  273. $item_total = $main_weight;
  274. $total_score = [$item_value_total, $item_total];
  275. $score = $scoredisplay->display_score($total_score, SCORE_DIV_PERCENT);
  276. $score = strip_tags($score);
  277. return $score;
  278. }
  279. if (empty($category)) {
  280. return new soap_fault('Server', '', 'Gradebook category not found');
  281. }
  282. return new soap_fault('Server', '', 'Score not found');
  283. }
  284. $server->wsdl->addComplexType(
  285. 'WSLpProgressParams',
  286. 'complexType',
  287. 'struct',
  288. 'all',
  289. '',
  290. [
  291. 'course_code' => [
  292. 'name' => 'course_code',
  293. 'type' => 'xsd:string',
  294. ],
  295. 'session_id' => [
  296. 'name' => 'session_id',
  297. 'type' => 'xsd:string',
  298. ],
  299. 'lp_id' => [
  300. 'name' => 'lp_id',
  301. 'type' => 'xsd:string',
  302. ],
  303. 'email' => [
  304. 'name' => 'email',
  305. 'type' => 'xsd:string',
  306. ],
  307. 'secret_key' => ['name' => 'secret_key', 'type' => 'xsd:string'],
  308. ]
  309. );
  310. // Register the method to expose
  311. $server->register(
  312. 'WSGetLpProgress', // method name
  313. ['params' => 'tns:WSLpProgressParams'], // input parameters
  314. ['return' => 'xsd:string'], // output parameters
  315. 'urn:WSGradebook', // namespace
  316. 'urn:WSGradebook#WSGetLpProgress', // soapaction
  317. 'rpc', // style
  318. 'encoded'
  319. );
  320. /**
  321. * @param array $params
  322. *
  323. * @return int|string
  324. */
  325. function WSGetLpProgress($params)
  326. {
  327. if (!WSHelperVerifyKey($params)) {
  328. return return_error(WS_ERROR_SECRET_KEY);
  329. }
  330. $courseCode = $params['course_code'];
  331. $courseInfo = api_get_course_info($courseCode);
  332. if (empty($courseInfo)) {
  333. return new soap_fault('Server', '', 'Course not found');
  334. }
  335. $sessionId = (int) $params['session_id'];
  336. if (!empty($sessionId)) {
  337. $sessionInfo = api_get_session_info($sessionId);
  338. if (empty($sessionInfo)) {
  339. return new soap_fault('Server', '', 'Session not found');
  340. }
  341. }
  342. $email = $params['email'];
  343. $userInfo = api_get_user_info_from_email($email);
  344. $userId = $userInfo['user_id'];
  345. if (empty($userInfo)) {
  346. return new soap_fault('Server', '', 'User not found');
  347. }
  348. $lpId = $params['lp_id'];
  349. $lp = new learnpath($courseCode, $lpId, $userId);
  350. if (empty($lp)) {
  351. return new soap_fault('Server', '', 'LP not found');
  352. }
  353. return $lp->progress_db;
  354. }
  355. $server->wsdl->addComplexType(
  356. 'WSAssignSkillParams',
  357. 'complexType',
  358. 'struct',
  359. 'all',
  360. '',
  361. [
  362. 'skill_id' => [
  363. 'name' => 'skill_id',
  364. 'type' => 'xsd:string',
  365. ],
  366. 'level' => [
  367. 'name' => 'level',
  368. 'type' => 'xsd:string',
  369. ],
  370. 'justification' => [
  371. 'name' => 'justification',
  372. 'type' => 'xsd:string',
  373. ],
  374. 'email' => [
  375. 'name' => 'email',
  376. 'type' => 'xsd:string',
  377. ],
  378. 'author_email' => [
  379. 'name' => 'author_email',
  380. 'type' => 'xsd:string',
  381. ],
  382. 'secret_key' => ['name' => 'secret_key', 'type' => 'xsd:string'],
  383. ]
  384. );
  385. // Register the method to expose
  386. $server->register(
  387. 'WSAssignSkill', // method name
  388. ['params' => 'tns:WSAssignSkillParams'], // input parameters
  389. ['return' => 'xsd:string'], // output parameters
  390. 'urn:WSGradebook', // namespace
  391. 'urn:WSGradebook:WSAssignSkill', // soapaction
  392. 'rpc', // style
  393. 'encoded'
  394. );
  395. /**
  396. * @param array $params
  397. *
  398. * @return int|string
  399. */
  400. function WSAssignSkill($params)
  401. {
  402. if (!WSHelperVerifyKey($params)) {
  403. return return_error(WS_ERROR_SECRET_KEY);
  404. }
  405. $em = Database::getManager();
  406. $skillManager = new SkillManager();
  407. $skillId = isset($params['skill_id']) ? $params['skill_id'] : 0;
  408. $skillRepo = $em->getRepository('ChamiloCoreBundle:Skill');
  409. $skill = $skillRepo->find($skillId);
  410. if (empty($skill)) {
  411. return new soap_fault('Server', '', 'Skill not found');
  412. }
  413. $justification = $params['justification'];
  414. if (strlen($justification) < 10) {
  415. return new soap_fault('Server', '', 'Justification smaller than 10 chars');
  416. }
  417. $level = (int) $params['level'];
  418. $email = $params['email'];
  419. $userInfo = api_get_user_info_from_email($email);
  420. if (empty($userInfo)) {
  421. return new soap_fault('Server', '', 'User not found');
  422. }
  423. $email = $params['author_email'];
  424. $authorInfo = api_get_user_info_from_email($email);
  425. if (empty($authorInfo)) {
  426. return new soap_fault('Server', '', 'Author not found');
  427. }
  428. $userId = $userInfo['user_id'];
  429. $user = api_get_user_entity($userId);
  430. $skillUser = $skillManager->addSkillToUserBadge(
  431. $user,
  432. $skill,
  433. $level,
  434. $justification,
  435. $authorInfo['id']
  436. );
  437. if (!empty($skillUser)) {
  438. return 1;
  439. }
  440. return 0;
  441. }
  442. // Use the request to (try to) invoke the service
  443. $GLOBALS['HTTP_RAW_POST_DATA'] = file_get_contents('php://input');
  444. $HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : '';
  445. // If you send your data in utf8 then this value must be false.
  446. $decodeUTF8 = api_get_setting('registration.soap.php.decode_utf8');
  447. if ($decodeUTF8 === 'true') {
  448. $server->decode_utf8 = true;
  449. } else {
  450. $server->decode_utf8 = false;
  451. }
  452. $server->service($HTTP_RAW_POST_DATA);