webservice_course.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. /**
  4. * @package chamilo.webservices
  5. */
  6. require_once __DIR__.'/../inc/global.inc.php';
  7. $libpath = api_get_path(LIBRARY_PATH);
  8. require_once __DIR__.'/webservice.php';
  9. /**
  10. * Web services available for the Course module. This class extends the WS class
  11. */
  12. class WSCourse extends WS
  13. {
  14. /**
  15. * Deletes a course (helper method)
  16. *
  17. * @param string Course id field name
  18. * @param string Course id value
  19. * @return mixed True if the course was successfully deleted, WSError otherwise
  20. */
  21. protected function deleteCourseHelper(
  22. $course_id_field_name,
  23. $course_id_value
  24. ) {
  25. $course_id = $this->getCourseId(
  26. $course_id_field_name,
  27. $course_id_value
  28. );
  29. if ($course_id instanceof WSError) {
  30. return $course_id;
  31. } else {
  32. $course_code = CourseManager::get_course_code_from_course_id(
  33. $course_id
  34. );
  35. CourseManager::delete_course($course_code);
  36. return true;
  37. }
  38. }
  39. /**
  40. * Deletes a course
  41. *
  42. * @param string API secret key
  43. * @param string Course id field name
  44. * @param string Course id value
  45. */
  46. public function DeleteCourse(
  47. $secret_key,
  48. $course_id_field_name,
  49. $course_id_value
  50. ) {
  51. $verifKey = $this->verifyKey($secret_key);
  52. if ($verifKey instanceof WSError) {
  53. $this->handleError($verifKey);
  54. } else {
  55. $result = $this->deleteCourseHelper(
  56. $course_id_field_name,
  57. $course_id_value
  58. );
  59. if ($result instanceof WSError) {
  60. $this->handleError($result);
  61. }
  62. }
  63. }
  64. /**
  65. * Deletes multiple courses
  66. *
  67. * @param string API secret key
  68. * @param array Array of courses with elements of the form array('course_id_field_name' => 'name_of_field', 'course_id_value' => 'value')
  69. * @return array Array with elements like array('course_id_value' => 'value', 'result' => array('code' => 0, 'message' => 'Operation was successful')). Note that if the result array contains a code different
  70. * than 0, an error occured
  71. */
  72. public function DeleteCourses($secret_key, $courses)
  73. {
  74. $verifKey = $this->verifyKey($secret_key);
  75. if ($verifKey instanceof WSError) {
  76. $this->handleError($verifKey);
  77. } else {
  78. $results = array();
  79. foreach ($courses as $course) {
  80. $result_tmp = array();
  81. $result_op = $this->deleteCourseHelper(
  82. $course['course_id_field_name'],
  83. $course['course_id_value']
  84. );
  85. $result_tmp['course_id_value'] = $course['course_id_value'];
  86. if ($result_op instanceof WSError) {
  87. // Return the error in the results
  88. $result_tmp['result'] = $result_op->toArray();
  89. } else {
  90. $result_tmp['result'] = $this->getSuccessfulResult();
  91. }
  92. $results[] = $result_tmp;
  93. }
  94. return $results;
  95. }
  96. }
  97. /**
  98. * Creates a course (helper method)
  99. *
  100. * @param string Title
  101. * @param string Category code
  102. * @param string Wanted code. If it's not defined, it will be generated automatically
  103. * @param string Tutor name
  104. * @param string Course admin user id field name
  105. * @param string Course admin user id value
  106. * @param string Course language
  107. * @param string Course id field name
  108. * @param string Course id value
  109. * @param array Course extra fields
  110. * @return mixed Generated id if creation was successful, WSError otherwise
  111. */
  112. protected function createCourseHelper(
  113. $title,
  114. $category_code,
  115. $wanted_code,
  116. $tutor_name,
  117. $course_admin_user_id_field_name,
  118. $course_admin_user_id_value,
  119. $language,
  120. $course_id_field_name,
  121. $course_id_value,
  122. $extras
  123. ) {
  124. // Add the original course id field name and value to the extra fields if needed
  125. $extras_associative = array();
  126. if ($course_id_field_name != "chamilo_course_id") {
  127. $extras_associative[$course_id_field_name] = $course_id_value;
  128. }
  129. foreach ($extras as $extra) {
  130. $extras_associative[$extra['field_name']] = $extra['field_value'];
  131. }
  132. $course_admin_id = $this->getUserId(
  133. $course_admin_user_id_field_name,
  134. $course_admin_user_id_value
  135. );
  136. if ($course_admin_id instanceof WSError) {
  137. return $course_admin_id;
  138. }
  139. if ($wanted_code == '') {
  140. $wanted_code = CourseManager::generate_course_code($title);
  141. }
  142. $result = create_course(
  143. $wanted_code,
  144. $title,
  145. $tutor_name,
  146. $category_code,
  147. $language,
  148. $course_admin_id,
  149. $this->_configuration['db_prefix'],
  150. 0
  151. );
  152. if (!$result) {
  153. return new WSError(202, 'There was an error creating the course');
  154. } else {
  155. // Update extra fields
  156. foreach ($extras_associative as $fname => $fvalue) {
  157. CourseManager::update_course_extra_field_value(
  158. $result,
  159. $fname,
  160. $fvalue
  161. );
  162. }
  163. // Get course id
  164. $course_info = CourseManager::get_course_information($result);
  165. return $course_info['real_id'];
  166. }
  167. }
  168. /**
  169. * Creates a course
  170. *
  171. * @param string API secret key
  172. * @param string Title
  173. * @param string Category code
  174. * @param string Wanted code. If it's not defined, it will be generated automatically
  175. * @param string Tutor name
  176. * @param string Course admin user id field name
  177. * @param string Course admin user id value
  178. * @param string Course language
  179. * @param string Course id field name
  180. * @param string Course id value
  181. * @param array Course extra fields
  182. * @return int Course id generated
  183. */
  184. public function CreateCourse(
  185. $secret_key,
  186. $title,
  187. $category_code,
  188. $wanted_code,
  189. $tutor_name,
  190. $course_admin_user_id_field_name,
  191. $course_admin_user_id_value,
  192. $language,
  193. $course_id_field_name,
  194. $course_id_value,
  195. $extras
  196. ) {
  197. // First, verify the secret key
  198. $verifKey = $this->verifyKey($secret_key);
  199. if ($verifKey instanceof WSError) {
  200. $this->handleError($verifKey);
  201. } else {
  202. $result = $this->createCourseHelper(
  203. $title,
  204. $category_code,
  205. $wanted_code,
  206. $tutor_name,
  207. $course_admin_user_id_field_name,
  208. $course_admin_user_id_value,
  209. $language,
  210. $course_id_field_name,
  211. $course_id_value,
  212. $extras
  213. );
  214. if ($result instanceof WSError) {
  215. $this->handleError($result);
  216. } else {
  217. return $result;
  218. }
  219. }
  220. }
  221. /**
  222. * Create multiple courses
  223. *
  224. * @param string API secret key
  225. * @param array Courses to be created, with elements following the structure presented in CreateCourse
  226. * @return array Array with elements of the form array('course_id_value' => 'original value sent', 'course_id_generated' => 'value_generated', 'result' => array('code' => 0, 'message' => 'Operation was successful'))
  227. */
  228. public function CreateCourses($secret_key, $courses)
  229. {
  230. // First, verify the secret key
  231. $verifKey = $this->verifyKey($secret_key);
  232. if ($verifKey instanceof WSError) {
  233. $this->handleError($verifKey);
  234. } else {
  235. $results = array();
  236. foreach ($courses as $course) {
  237. $result_tmp = array();
  238. // re-initialize variables just in case
  239. $title = $category_code = $wanted_code = $tutor_name = $course_admin_user_id_field_name = $course_admin_user_id_value = $language = $course_id_field_name = $course_id_value = $extras = 0;
  240. extract($course);
  241. $result = $this->createCourseHelper(
  242. $title,
  243. $category_code,
  244. $wanted_code,
  245. $tutor_name,
  246. $course_admin_user_id_field_name,
  247. $course_admin_user_id_value,
  248. $language,
  249. $course_id_field_name,
  250. $course_id_value,
  251. $extras
  252. );
  253. if ($result instanceof WSError) {
  254. $result_tmp['result'] = $result->toArray();
  255. $result_tmp['course_id_value'] = $course_id_value;
  256. $result_tmp['course_id_generated'] = 0;
  257. } else {
  258. $result_tmp['result'] = $this->getSuccessfulResult();
  259. $result_tmp['course_id_value'] = $course_id_value;
  260. $result_tmp['course_id_generated'] = $result;
  261. }
  262. $results[] = $result_tmp;
  263. }
  264. return $results;
  265. }
  266. }
  267. /**
  268. * Edits a course (helper method)
  269. *
  270. * @param string Course id field name
  271. * @param string Course id value
  272. * @param string Title
  273. * @param string Category code
  274. * @param string Department name
  275. * @param string Department url
  276. * @param string Course language
  277. * @param int Visibility
  278. * @param int Subscribe (0 = denied, 1 = allowed)
  279. * @param int Unsubscribe (0 = denied, 1 = allowed)
  280. * @param string Visual code
  281. * @param array Course extra fields
  282. * @return mixed True in case of success, WSError otherwise
  283. */
  284. protected function editCourseHelper(
  285. $course_id_field_name,
  286. $course_id_value,
  287. $title,
  288. $category_code,
  289. $department_name,
  290. $department_url,
  291. $language,
  292. $visibility,
  293. $subscribe,
  294. $unsubscribe,
  295. $visual_code,
  296. $extras
  297. ) {
  298. $course_id = $this->getCourseId(
  299. $course_id_field_name,
  300. $course_id_value
  301. );
  302. if ($course_id instanceof WSError) {
  303. return $course_id;
  304. } else {
  305. $attributes = array();
  306. if (!empty($title)) {
  307. $attributes['title'] = $title;
  308. }
  309. if (!empty($category_code)) {
  310. $attributes['category_code'] = $category_code;
  311. }
  312. if (!empty($department_name)) {
  313. $attributes['department_name'] = $department_name;
  314. }
  315. if (!empty($department_url)) {
  316. $attributes['department_url'] = $department_url;
  317. }
  318. if (!empty($language)) {
  319. $attributes['course_language'] = $language;
  320. }
  321. if ($visibility != '') {
  322. $attributes['visibility'] = (int) $visibility;
  323. }
  324. if ($subscribe != '') {
  325. $attributes['subscribe'] = (int) $subscribe;
  326. }
  327. if ($unsubscribe != '') {
  328. $attributes['unsubscribe'] = (int) $unsubscribe;
  329. }
  330. if (!empty($visual_code)) {
  331. $attributes['visual_code'] = $visual_code;
  332. }
  333. if (!empty($attributes)) {
  334. CourseManager::update_attributes($course_id, $attributes);
  335. }
  336. if (!empty($extras)) {
  337. $course_code = CourseManager::get_course_code_from_course_id(
  338. $course_id
  339. );
  340. $extras_associative = array();
  341. foreach ($extras as $extra) {
  342. $extras_associative[$extra['field_name']] = $extra['field_value'];
  343. }
  344. foreach ($extras_associative as $fname => $fvalue) {
  345. CourseManager::update_extra_field_value(
  346. $course_code,
  347. $fname,
  348. $fvalue
  349. );
  350. }
  351. }
  352. return true;
  353. }
  354. }
  355. /**
  356. * Edits a course
  357. *
  358. * @param string API secret key
  359. * @param string Course id field name
  360. * @param string Course id value
  361. * @param string Title
  362. * @param string Category code
  363. * @param string Department name
  364. * @param string Department url
  365. * @param string Course language
  366. * @param int Visibility
  367. * @param int Subscribe (0 = denied, 1 = allowed)
  368. * @param int Unsubscribe (0 = denied, 1 = allowed)
  369. * @param string Visual code
  370. * @param array Course extra fields
  371. */
  372. public function EditCourse(
  373. $secret_key,
  374. $course_id_field_name,
  375. $course_id_value,
  376. $title,
  377. $category_code,
  378. $department_name,
  379. $department_url,
  380. $language,
  381. $visibility,
  382. $subscribe,
  383. $unsubscribe,
  384. $visual_code,
  385. $extras
  386. ) {
  387. $verifKey = $this->verifyKey($secret_key);
  388. if ($verifKey instanceof WSError) {
  389. $this->handleError($verifKey);
  390. } else {
  391. $result = $this->editCourseHelper(
  392. $course_id_field_name,
  393. $course_id_value,
  394. $title,
  395. $category_code,
  396. $department_name,
  397. $department_url,
  398. $language,
  399. $visibility,
  400. $subscribe,
  401. $unsubscribe,
  402. $visual_code,
  403. $extras
  404. );
  405. if ($result instanceof WSError) {
  406. $this->handleError($result);
  407. }
  408. }
  409. }
  410. /**
  411. * List courses
  412. *
  413. * @param string API secret key
  414. * @param string A list of visibility filter we want to apply
  415. * @return array An array with elements of the form ('id' => 'Course internal id', 'code' => 'Course code', 'title' => 'Course title', 'language' => 'Course language', 'visibility' => 'Course visibility',
  416. * 'category_name' => 'Name of the category of the course', 'number_students' => 'Number of students in the course', 'external_course_id' => 'External course id')
  417. */
  418. public function ListCourses(
  419. $secret_key,
  420. $visibility = 'public,public-registered,private,closed'
  421. ) {
  422. $verifKey = $this->verifyKey($secret_key);
  423. if ($verifKey instanceof WSError) {
  424. $this->handleError($verifKey);
  425. } else {
  426. $visibilities = split(',', $visibility);
  427. $vis = array(
  428. 'public' => '3',
  429. 'public-registered' => '2',
  430. 'private' => '1',
  431. 'closed' => '0',
  432. );
  433. foreach ($visibilities as $p => $visibility) {
  434. $visibilities[$p] = $vis[$visibility];
  435. }
  436. $courses_result = array();
  437. $category_names = array();
  438. $courses = CourseManager::get_courses_list();
  439. foreach ($courses as $course) {
  440. //skip elements that do not match required visibility
  441. if (!in_array($course['visibility'], $visibilities)) {
  442. continue;
  443. }
  444. $course_tmp = array();
  445. $course_tmp['id'] = $course['id'];
  446. $course_tmp['code'] = $course['code'];
  447. $course_tmp['title'] = $course['title'];
  448. $course_tmp['language'] = $course['course_language'];
  449. $course_tmp['visibility'] = $course['visibility'];
  450. // Determining category name
  451. if ($category_names[$course['category_code']]) {
  452. $course_tmp['category_name'] = $category_names[$course['category_code']];
  453. } else {
  454. $category = CourseManager::get_course_category(
  455. $course['category_code']
  456. );
  457. $category_names[$course['category_code']] = $category['name'];
  458. $course_tmp['category_name'] = $category['name'];
  459. }
  460. // Determining number of students registered in course
  461. $user_list = CourseManager::get_user_list_from_course_code(
  462. $course['code'],
  463. 0
  464. );
  465. $course_tmp['number_students'] = count($user_list);
  466. // Determining external course id - this code misses the external course id field name
  467. // $course_tmp['external_course_id'] = CourseManager::get_course_extra_field_value($course_field_name, $course['code']);
  468. $courses_result[] = $course_tmp;
  469. }
  470. return $courses_result;
  471. }
  472. }
  473. /**
  474. * Subscribe or unsubscribe user to a course (helper method)
  475. *
  476. * @param string Course id field name. Use "chamilo_course_id" to use internal id
  477. * @param string Course id value.
  478. * @param string User id field name. Use "chamilo_user_id" to use internal id
  479. * @param string User id value
  480. * @param int Set to 1 to subscribe, 0 to unsubscribe
  481. * @param int Status (STUDENT or TEACHER) Used for subscription only
  482. * @return mixed True if subscription or unsubscription was successful, false otherwise
  483. */
  484. protected function changeUserSubscription(
  485. $course_id_field_name,
  486. $course_id_value,
  487. $user_id_field_name,
  488. $user_id_value,
  489. $state,
  490. $status = STUDENT
  491. ) {
  492. $course_id = $this->getCourseId(
  493. $course_id_field_name,
  494. $course_id_value
  495. );
  496. if ($course_id instanceof WSError) {
  497. return $course_id;
  498. } else {
  499. $user_id = $this->getUserId($user_id_field_name, $user_id_value);
  500. if ($user_id instanceof WSError) {
  501. return $user_id;
  502. } else {
  503. $course_code = CourseManager::get_course_code_from_course_id(
  504. $course_id
  505. );
  506. if ($state == 0) {
  507. // Unsubscribe user
  508. CourseManager::unsubscribe_user($user_id, $course_code);
  509. return true;
  510. } else {
  511. // Subscribe user
  512. if (CourseManager::subscribe_user(
  513. $user_id,
  514. $course_code,
  515. $status
  516. )
  517. ) {
  518. return true;
  519. } else {
  520. return new WSError(
  521. 203,
  522. 'An error occured subscribing to this course'
  523. );
  524. }
  525. }
  526. }
  527. }
  528. }
  529. /**
  530. * Subscribe user to a course
  531. *
  532. * @param string API secret key
  533. * @param string Course id field name. Use "chamilo_course_id" to use internal id
  534. * @param string Course id value.
  535. * @param string User id field name. Use "chamilo_user_id" to use internal id
  536. * @param string User id value
  537. * @param int Status (1 = Teacher, 5 = Student)
  538. */
  539. public function SubscribeUserToCourse(
  540. $secret_key,
  541. $course_id_field_name,
  542. $course_id_value,
  543. $user_id_field_name,
  544. $user_id_value,
  545. $status
  546. ) {
  547. $verifKey = $this->verifyKey($secret_key);
  548. if ($verifKey instanceof WSError) {
  549. $this->handleError($verifKey);
  550. } else {
  551. $result = $this->changeUserSubscription(
  552. $course_id_field_name,
  553. $course_id_value,
  554. $user_id_field_name,
  555. $user_id_value,
  556. 1,
  557. $status
  558. );
  559. if ($result instanceof WSError) {
  560. $this->handleError($result);
  561. }
  562. }
  563. }
  564. /**
  565. * Unsusbscribe user from course
  566. *
  567. * @param string API secret key
  568. * @param string Course id field name. Use "chamilo_course_id" to use internal id
  569. * @param string Course id value.
  570. * @param string User id field name. Use "chamilo_user_id" to use internal id
  571. * @param string User id value
  572. */
  573. public function UnsubscribeUserFromCourse(
  574. $secret_key,
  575. $course_id_field_name,
  576. $course_id_value,
  577. $user_id_field_name,
  578. $user_id_value
  579. ) {
  580. $verifKey = $this->verifyKey($secret_key);
  581. if ($verifKey instanceof WSError) {
  582. $this->handleError($verifKey);
  583. } else {
  584. $result = $this->changeUserSubscription(
  585. $course_id_field_name,
  586. $course_id_value,
  587. $user_id_field_name,
  588. $user_id_value,
  589. 0
  590. );
  591. if ($result instanceof WSError) {
  592. $this->handleError($result);
  593. }
  594. }
  595. }
  596. /**
  597. * Returns the descriptions of a course, along with their id
  598. *
  599. * @param string API secret key
  600. * @param string Course id field name
  601. * @param string Course id value
  602. * @return array Returns an array with elements of the form ('course_desc_id' => 1, 'course_desc_title' => 'Title', 'course_desc_content' => 'Content')
  603. */
  604. public function GetCourseDescriptions(
  605. $secret_key,
  606. $course_id_field_name,
  607. $course_id_value
  608. ) {
  609. $verifKey = $this->verifyKey($secret_key);
  610. if ($verifKey instanceof WSError) {
  611. $this->handleError($verifKey);
  612. } else {
  613. $course_id = $this->getCourseId(
  614. $course_id_field_name,
  615. $course_id_value
  616. );
  617. if ($course_id instanceof WSError) {
  618. return $course_id;
  619. } else {
  620. // Course exists, get its descriptions
  621. $descriptions = CourseDescription::get_descriptions($course_id);
  622. $results = array();
  623. foreach ($descriptions as $description) {
  624. $results[] = array(
  625. 'course_desc_id' => $description->get_description_type(
  626. ),
  627. 'course_desc_title' => $description->get_title(),
  628. 'course_desc_content' => $description->get_content(),
  629. );
  630. }
  631. return $results;
  632. }
  633. }
  634. }
  635. /**
  636. * Edit course description
  637. *
  638. * @param string API secret key
  639. * @param string Course id field name
  640. * @param string Course id value
  641. * @param int Category id from course description
  642. * @param string Description title
  643. * @param string Course description content
  644. */
  645. public function EditCourseDescription(
  646. $secret_key,
  647. $course_id_field_name,
  648. $course_id_value,
  649. $course_desc_id,
  650. $course_desc_title,
  651. $course_desc_content
  652. ) {
  653. $verifKey = $this->verifyKey($secret_key);
  654. if ($verifKey instanceof WSError) {
  655. $this->handleError($verifKey);
  656. } else {
  657. $course_id = $this->getCourseId(
  658. $course_id_field_name,
  659. $course_id_value
  660. );
  661. if ($course_id instanceof WSError) {
  662. return $course_id;
  663. } else {
  664. // Create the new course description
  665. $cd = new CourseDescription();
  666. $cd->set_description_type($course_desc_id);
  667. $cd->set_title($course_desc_title);
  668. $cd->set_content($course_desc_content);
  669. $cd->set_session_id(0);
  670. // Get course info
  671. $course_info = CourseManager::get_course_information(
  672. CourseManager::get_course_code_from_course_id($course_id)
  673. );
  674. $cd->set_course_id($course_info['real_id']);
  675. // Check if this course description exists
  676. $descriptions = CourseDescription::get_descriptions($course_id);
  677. $exists = false;
  678. foreach ($descriptions as $description) {
  679. if ($description->get_description_type(
  680. ) == $course_desc_id
  681. ) {
  682. $exists = true;
  683. }
  684. }
  685. if (!$exists) {
  686. $cd->set_progress(0);
  687. $cd->insert();
  688. } else {
  689. $cd->update();
  690. }
  691. }
  692. }
  693. }
  694. }