Rest.php 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. use Chamilo\CoreBundle\Entity\Course;
  4. use Chamilo\CoreBundle\Entity\ExtraFieldValues;
  5. use Chamilo\CourseBundle\Entity\Repository\CAnnouncementRepository;
  6. use Chamilo\CourseBundle\Entity\Repository\CNotebookRepository;
  7. use Chamilo\CourseBundle\Entity\CLpCategory;
  8. use Chamilo\CoreBundle\Entity\Session;
  9. use Chamilo\UserBundle\Entity\User;
  10. /**
  11. * Class RestApi
  12. */
  13. class Rest extends WebService
  14. {
  15. const SERVIVE_NAME = 'MsgREST';
  16. const EXTRA_FIELD_GCM_REGISTRATION = 'gcm_registration_id';
  17. const GET_AUTH = 'authenticate';
  18. const GET_USER_MESSAGES = 'user_messages';
  19. const SAVE_GCM_ID = 'gcm_id';
  20. const GET_USER_COURSES = 'user_courses';
  21. const GET_PROFILE = 'user_profile';
  22. const GET_COURSE_INFO = 'course_info';
  23. const GET_COURSE_DESCRIPTIONS = 'course_descriptions';
  24. const GET_COURSE_DOCUMENTS = 'course_documents';
  25. const GET_COURSE_ANNOUNCEMENTS = 'course_announcements';
  26. const GET_COURSE_ANNOUNCEMENT = 'course_announcement';
  27. const GET_COURSE_AGENDA = 'course_agenda';
  28. const GET_COURSE_NOTEBOOKS = 'course_notebooks';
  29. const GET_COURSE_FORUM_CATEGORIES = 'course_forumcategories';
  30. const GET_COURSE_FORUM = 'course_forum';
  31. const GET_COURSE_FORUM_THREAD = 'course_forumthread';
  32. const GET_COURSE_LEARNPATHS = 'course_learnpaths';
  33. const GET_COURSE_LEARNPATH = 'course_learnpath';
  34. const SAVE_FORUM_POST = 'save_forum_post';
  35. const GET_USER_SESSIONS = 'user_sessions';
  36. const SAVE_USER_MESSAGE = 'save_user_message';
  37. const GET_MESSAGE_USERS = 'message_users';
  38. const SAVE_COURSE_NOTEBOOK = 'save_course_notebook';
  39. const SAVE_FORUM_THREAD = 'save_forum_thread';
  40. const EXTRAFIELD_GCM_ID = 'gcm_registration_id';
  41. /**
  42. * @var Session
  43. */
  44. private $session;
  45. /**
  46. * @var Course
  47. */
  48. private $course;
  49. /**
  50. * Rest constructor.
  51. * @param string $username
  52. * @param string $apiKey
  53. */
  54. public function __construct($username, $apiKey)
  55. {
  56. parent::__construct($username, $apiKey);
  57. }
  58. /**
  59. * Set the current course
  60. * @param int $id
  61. * @throws Exception
  62. */
  63. public function setCourse($id)
  64. {
  65. if (!$id) {
  66. $this->course = null;
  67. return;
  68. }
  69. $em = Database::getManager();
  70. /** @var Course $course */
  71. $course = $em->find('ChamiloCoreBundle:Course', $id);
  72. if (!$course) {
  73. throw new Exception(get_lang('NoCourse'));
  74. }
  75. $this->course = $course;
  76. }
  77. /** Set the current session
  78. * @param int $id
  79. * @throws Exception
  80. */
  81. public function setSession($id)
  82. {
  83. if (!$id) {
  84. $this->session = null;
  85. return;
  86. }
  87. $em = Database::getManager();
  88. /** @var Session $session */
  89. $session = $em->find('ChamiloCoreBundle:Session', $id);
  90. if (!$session) {
  91. throw new Exception(get_lang('NoSession'));
  92. }
  93. $this->session = $session;
  94. }
  95. /**
  96. * @param string $username
  97. * @param string $apiKeyToValidate
  98. * @return Rest
  99. * @throws Exception
  100. */
  101. public static function validate($username, $apiKeyToValidate)
  102. {
  103. $apiKey = self::findUserApiKey($username, self::SERVIVE_NAME);
  104. if ($apiKey != $apiKeyToValidate) {
  105. throw new Exception(get_lang('InvalidApiKey'));
  106. }
  107. return new self($username, $apiKey);
  108. }
  109. /**
  110. * Create the gcm_registration_id extra field for users
  111. */
  112. public static function init()
  113. {
  114. $extraField = new ExtraField('user');
  115. $fieldInfo = $extraField->get_handler_field_info_by_field_variable(self::EXTRA_FIELD_GCM_REGISTRATION);
  116. if (empty($fieldInfo)) {
  117. $extraField->save([
  118. 'variable' => self::EXTRA_FIELD_GCM_REGISTRATION,
  119. 'field_type' => ExtraField::FIELD_TYPE_TEXT,
  120. 'display_text' => self::EXTRA_FIELD_GCM_REGISTRATION
  121. ]);
  122. }
  123. }
  124. /**
  125. * @param string $registrationId
  126. * @return bool
  127. */
  128. public function setGcmId($registrationId)
  129. {
  130. $registrationId = Security::remove_XSS($registrationId);
  131. $extraFieldValue = new ExtraFieldValue('user');
  132. return $extraFieldValue->save([
  133. 'variable' => self::EXTRA_FIELD_GCM_REGISTRATION,
  134. 'value' => $registrationId,
  135. 'item_id' => $this->user->getId()
  136. ]);
  137. }
  138. /**
  139. * @param int $lastMessageId
  140. * @return array
  141. */
  142. public function getUserMessages($lastMessageId = 0)
  143. {
  144. $lastMessages = MessageManager::getMessagesFromLastReceivedMessage($this->user->getId(), $lastMessageId);
  145. $messages = [];
  146. foreach ($lastMessages as $message) {
  147. $hasAttachments = MessageManager::hasAttachments($message['id']);
  148. $messages[] = array(
  149. 'id' => $message['id'],
  150. 'title' => $message['title'],
  151. 'sender' => array(
  152. 'id' => $message['user_id'],
  153. 'lastname' => $message['lastname'],
  154. 'firstname' => $message['firstname'],
  155. 'completeName' => api_get_person_name($message['firstname'], $message['lastname']),
  156. ),
  157. 'sendDate' => $message['send_date'],
  158. 'content' => $message['content'],
  159. 'hasAttachments' => $hasAttachments,
  160. 'url' => ''
  161. );
  162. }
  163. return $messages;
  164. }
  165. /**
  166. * Get the user courses
  167. * @return array
  168. */
  169. public function getUserCourses()
  170. {
  171. $courses = CourseManager::get_courses_list_by_user_id($this->user->getId());
  172. $data = [];
  173. foreach ($courses as $courseId) {
  174. /** @var Course $course */
  175. $course = Database::getManager()->find('ChamiloCoreBundle:Course', $courseId['real_id']);
  176. $teachers = CourseManager::get_teacher_list_from_course_code_to_string($course->getCode());
  177. $data[] = [
  178. 'id' => $course->getId(),
  179. 'title' => $course->getTitle(),
  180. 'code' => $course->getCode(),
  181. 'directory' => $course->getDirectory(),
  182. 'urlPicture' => $course->getPicturePath(true),
  183. 'teachers' => $teachers
  184. ];
  185. }
  186. return $data;
  187. }
  188. /**
  189. * @return array
  190. * @throws Exception
  191. */
  192. public function getCourseInfo()
  193. {
  194. $teachers = CourseManager::get_teacher_list_from_course_code_to_string($this->course->getCode());
  195. $tools = CourseHome::get_tools_category(
  196. TOOL_STUDENT_VIEW,
  197. $this->course->getId(),
  198. $this->session ? $this->session->getId() : 0
  199. );
  200. return [
  201. 'id' => $this->course->getId(),
  202. 'title' => $this->course->getTitle(),
  203. 'code' => $this->course->getCode(),
  204. 'directory' => $this->course->getDirectory(),
  205. 'urlPicture' => $this->course->getPicturePath(true),
  206. 'teachers' => $teachers,
  207. 'tools' => array_map(
  208. function($tool) {
  209. return ['type' => $tool['name']];
  210. },
  211. $tools
  212. )
  213. ];
  214. }
  215. /**
  216. * Get the course descriptions
  217. * @return array
  218. * @throws Exception
  219. */
  220. public function getCourseDescriptions()
  221. {
  222. $descriptions = CourseDescription::get_descriptions($this->course->getId());
  223. $results = [];
  224. /** @var CourseDescription $description */
  225. foreach ($descriptions as $description) {
  226. $results[] = [
  227. 'id' => $description->get_description_type(),
  228. 'title' => $description->get_title(),
  229. 'content' => str_replace('src="/', 'src="'.api_get_path(WEB_PATH), $description->get_content())
  230. ];
  231. }
  232. return $results;
  233. }
  234. /**
  235. * @param int $directoryId
  236. * @return array
  237. * @throws Exception
  238. */
  239. public function getCourseDocuments($directoryId = 0)
  240. {
  241. /** @var string $path */
  242. $path = '/';
  243. $sessionId = $this->session ? $this->session->getId() : 0;
  244. if ($directoryId) {
  245. $directory = DocumentManager::get_document_data_by_id(
  246. $directoryId,
  247. $this->course->getCode(),
  248. false,
  249. $sessionId
  250. );
  251. if (!$directory) {
  252. throw new Exception('NoDataAvailable');
  253. }
  254. $path = $directory['path'];
  255. }
  256. require_once api_get_path(LIBRARY_PATH).'fileDisplay.lib.php';
  257. $courseInfo = api_get_course_info_by_id($this->course->getId());
  258. $documents = DocumentManager::get_all_document_data(
  259. $courseInfo,
  260. $path,
  261. 0,
  262. null,
  263. false,
  264. false,
  265. $sessionId
  266. );
  267. $results = [];
  268. if (is_array($documents)) {
  269. $webPath = api_get_path(WEB_CODE_PATH).'document/document.php?';
  270. /** @var array $document */
  271. foreach ($documents as $document) {
  272. if ($document['visibility'] != '1') {
  273. continue;
  274. }
  275. $icon = $document['filetype'] == 'file'
  276. ? choose_image($document['path'])
  277. : chooseFolderIcon($document['path']);
  278. $results[] = [
  279. 'id' => $document['id'],
  280. 'type' => $document['filetype'],
  281. 'title' => $document['title'],
  282. 'path' => $document['path'],
  283. 'url' => $webPath.http_build_query([
  284. 'username' => $this->user->getUsername(),
  285. 'api_key' => $this->apiKey,
  286. 'cidReq' => $this->course->getCode(),
  287. 'id_session' => $sessionId,
  288. 'gidReq' => 0,
  289. 'gradebook' => 0,
  290. 'origin' => '',
  291. 'action' => 'download',
  292. 'id' => $document['id']
  293. ]),
  294. 'icon' => $icon,
  295. 'size' => format_file_size($document['size'])
  296. ];
  297. }
  298. }
  299. return $results;
  300. }
  301. /**
  302. * @param int $courseId
  303. * @return array
  304. * @throws Exception
  305. */
  306. public function getCourseAnnouncements()
  307. {
  308. $sessionId = $this->session ? $this->session->getId() : 0;
  309. $announcements = AnnouncementManager::getAnnouncements(
  310. null,
  311. null,
  312. false,
  313. null,
  314. null,
  315. null,
  316. null,
  317. null,
  318. 0,
  319. $this->user->getId(),
  320. $this->course->getId(),
  321. $sessionId
  322. );
  323. $announcements = array_map(function($announcement) {
  324. return [
  325. 'id' => intval($announcement['id']),
  326. 'title' => strip_tags($announcement['title']),
  327. 'creatorName' => strip_tags($announcement['username']),
  328. 'date' => strip_tags($announcement['insert_date'])
  329. ];
  330. }, $announcements);
  331. return $announcements;
  332. }
  333. /**
  334. * @param int $announcementId
  335. * @return array
  336. * @throws Exception
  337. */
  338. public function getCourseAnnouncement($announcementId)
  339. {
  340. $sessionId = $this->session ? $this->session->getId() : 0;
  341. $announcement = AnnouncementManager::getAnnouncementInfoById(
  342. $announcementId,
  343. $this->course->getId(),
  344. $this->user->getId()
  345. );
  346. if (!$announcement) {
  347. throw new Exception(get_lang('NoAnnouncement'));
  348. }
  349. return [
  350. 'id' => intval($announcement['announcement']->getIid()),
  351. 'title' => $announcement['announcement']->getTitle(),
  352. 'creatorName' => $announcement['item_property']->getInsertUser()->getCompleteName(),
  353. 'date' => api_convert_and_format_date($announcement['item_property']->getInsertDate(), DATE_TIME_FORMAT_LONG_24H),
  354. 'content' => AnnouncementManager::parse_content(
  355. $this->user->getId(),
  356. $announcement['announcement']->getContent(),
  357. $this->course->getCode(),
  358. $sessionId
  359. )
  360. ];
  361. }
  362. /**
  363. * @return array
  364. * @throws Exception
  365. */
  366. public function getCourseAgenda()
  367. {
  368. $sessionId = $this->session ? $this->session->getId() : 0;
  369. $agenda = new Agenda(
  370. 'course',
  371. $this->user->getId(),
  372. $this->course->getId(),
  373. $sessionId
  374. );
  375. $result = $agenda->parseAgendaFilter(null);
  376. $start = new DateTime(api_get_utc_datetime(), new DateTimeZone('UTC'));
  377. $start->modify('first day of this month');
  378. $start->setTime(0, 0, 0);
  379. $end = new DateTime(api_get_utc_datetime(), new DateTimeZone('UTC'));
  380. $end->modify('last day of this month');
  381. $end->setTime(23, 59, 59);
  382. $groupId = current($result['groups']);
  383. $userId = current($result['users']);
  384. $events = $agenda->getEvents(
  385. $start->getTimestamp(),
  386. $end->getTimestamp(),
  387. $this->course->getId(),
  388. $groupId,
  389. $userId,
  390. 'array'
  391. );
  392. if (!is_array($events)) {
  393. return [];
  394. }
  395. $webPath = api_get_path(WEB_PATH);
  396. return array_map(
  397. function($event) use ($webPath) {
  398. return [
  399. 'id' => intval($event['unique_id']),
  400. 'title' => $event['title'],
  401. 'content' => str_replace('src="/', 'src="'.$webPath, $event['description']),
  402. 'startDate' => $event['start_date_localtime'],
  403. 'endDate' => $event['end_date_localtime'],
  404. 'isAllDay' => $event['allDay'] ? true : false
  405. ];
  406. },
  407. $events
  408. );
  409. }
  410. /**
  411. * @return array
  412. * @throws Exception
  413. */
  414. public function getCourseNotebooks()
  415. {
  416. $em = Database::getManager();
  417. /** @var CNotebookRepository $notebooksRepo */
  418. $notebooksRepo = $em->getRepository('ChamiloCourseBundle:CNotebook');
  419. $notebooks = $notebooksRepo->findByUser($this->user, $this->course, $this->session);
  420. return array_map(
  421. function(\Chamilo\CourseBundle\Entity\CNotebook $notebook) {
  422. return [
  423. 'id' => $notebook->getIid(),
  424. 'title' => $notebook->getTitle(),
  425. 'description' => $notebook->getDescription(),
  426. 'creationDate' => api_format_date(
  427. $notebook->getCreationDate()->getTimestamp()
  428. ),
  429. 'updateDate' => api_format_date(
  430. $notebook->getUpdateDate()->getTimestamp()
  431. )
  432. ];
  433. },
  434. $notebooks
  435. );
  436. }
  437. /**
  438. * @return array
  439. * @throws Exception
  440. */
  441. public function getCourseForumCategories()
  442. {
  443. $sessionId = $this->session ? $this->session->getId() : 0;
  444. $webCoursePath = api_get_path(WEB_COURSE_PATH).$this->course->getDirectory().'/upload/forum/images/';
  445. require_once api_get_path(SYS_CODE_PATH).'forum/forumfunction.inc.php';
  446. $categoriesFullData = get_forum_categories('', $this->course->getId(), $sessionId);
  447. $categories = [];
  448. $includeGroupsForums = api_get_setting('display_groups_forum_in_general_tool') === 'true';
  449. $forumsFullData = get_forums('', $this->course->getCode(), $includeGroupsForums, $sessionId);
  450. $forums = [];
  451. foreach ($forumsFullData as $forumId => $forumInfo) {
  452. $forum = [
  453. 'id' => intval($forumInfo['iid']),
  454. 'catId' => intval($forumInfo['forum_category']),
  455. 'title' => $forumInfo['forum_title'],
  456. 'description' => $forumInfo['forum_comment'],
  457. 'image' => $forumInfo['forum_image'] ? ($webCoursePath.$forumInfo['forum_image']) : '',
  458. 'numberOfThreads' => isset($forumInfo['number_of_threads']) ? intval($forumInfo['number_of_threads']) : 0,
  459. 'lastPost' => null
  460. ];
  461. $lastPostInfo = get_last_post_information($forumId, false, $this->course->getId(), $sessionId);
  462. if ($lastPostInfo) {
  463. $forum['lastPost'] = [
  464. 'date' => api_convert_and_format_date($lastPostInfo['last_post_date']),
  465. 'user' => api_get_person_name(
  466. $lastPostInfo['last_poster_firstname'],
  467. $lastPostInfo['last_poster_lastname']
  468. )
  469. ];
  470. }
  471. $forums[] = $forum;
  472. }
  473. foreach ($categoriesFullData as $category) {
  474. $categoryForums = array_filter(
  475. $forums,
  476. function(array $forum) use ($category) {
  477. if ($forum['catId'] != $category['cat_id']) {
  478. return false;
  479. }
  480. return true;
  481. }
  482. );
  483. $categories[] = [
  484. 'id' => intval($category['iid']),
  485. 'title' => $category['cat_title'],
  486. 'catId' => intval($category['cat_id']),
  487. 'description' => $category['cat_comment'],
  488. 'forums' => $categoryForums,
  489. 'courseId' => $this->course->getId()
  490. ];
  491. }
  492. return $categories;
  493. }
  494. /**
  495. * @param int $forumId
  496. * @return array
  497. * @throws Exception
  498. */
  499. public function getCourseForum($forumId)
  500. {
  501. require_once api_get_path(SYS_CODE_PATH).'forum/forumfunction.inc.php';
  502. $sessionId = $this->session ? $this->session->getId() : 0;
  503. $forumInfo = get_forums($forumId, $this->course->getCode(), true, $sessionId);
  504. if (!isset($forumInfo['iid'])) {
  505. throw new Exception(get_lang('NoForum'));
  506. }
  507. $webCoursePath = api_get_path(WEB_COURSE_PATH).$this->course->getDirectory().'/upload/forum/images/';
  508. $forum = [
  509. 'id' => $forumInfo['iid'],
  510. 'title' => $forumInfo['forum_title'],
  511. 'description' => $forumInfo['forum_comment'],
  512. 'image' => $forumInfo['forum_image'] ? ($webCoursePath.$forumInfo['forum_image']) : '',
  513. 'threads' => []
  514. ];
  515. $threads = get_threads($forumInfo['iid'], $this->course->getId(), $sessionId);
  516. foreach ($threads as $thread) {
  517. $forum['threads'][] = [
  518. 'id' => $thread['iid'],
  519. 'title' => $thread['thread_title'],
  520. 'lastEditDate' => api_convert_and_format_date($thread['lastedit_date'], DATE_TIME_FORMAT_LONG_24H),
  521. 'numberOfReplies' => $thread['thread_replies'],
  522. 'numberOfViews' => $thread['thread_views'],
  523. 'author' => api_get_person_name($thread['firstname'], $thread['lastname'])
  524. ];
  525. }
  526. return $forum;
  527. }
  528. /**
  529. * @param int $forumId
  530. * @param int $threadId
  531. * @return array
  532. */
  533. public function getCourseForumThread($forumId, $threadId)
  534. {
  535. require_once api_get_path(SYS_CODE_PATH).'forum/forumfunction.inc.php';
  536. $sessionId = $this->session ? $this->session->getId() : 0;
  537. $threadInfo = get_thread_information($forumId, $threadId, $sessionId);
  538. $thread = [
  539. 'id' => intval($threadInfo['iid']),
  540. 'cId' => intval($threadInfo['c_id']),
  541. 'title' => $threadInfo['thread_title'],
  542. 'forumId' => intval($threadInfo['forum_id']),
  543. 'posts' => []
  544. ];
  545. $forumInfo = get_forums($threadInfo['forum_id'], $this->course->getCode(), true, $sessionId);
  546. $postsInfo = getPosts($forumInfo, $threadInfo['iid'], 'ASC');
  547. foreach ($postsInfo as $postInfo) {
  548. $thread['posts'][] = [
  549. 'id' => $postInfo['iid'],
  550. 'title' => $postInfo['post_title'],
  551. 'text' => $postInfo['post_text'],
  552. 'author' => api_get_person_name($postInfo['firstname'], $postInfo['lastname']),
  553. 'date' => api_convert_and_format_date($postInfo['post_date'], DATE_TIME_FORMAT_LONG_24H),
  554. 'parentId' => $postInfo['post_parent_id']
  555. ];
  556. }
  557. return $thread;
  558. }
  559. /**
  560. * @return array
  561. */
  562. public function getUserProfile()
  563. {
  564. $pictureInfo = UserManager::get_user_picture_path_by_id($this->user->getId(), 'web');
  565. $result = [
  566. 'pictureUri' => $pictureInfo['dir'].$pictureInfo['file'],
  567. 'fullName' => $this->user->getCompleteName(),
  568. 'username' => $this->user->getUsername(),
  569. 'officialCode' => $this->user->getOfficialCode(),
  570. 'phone' => $this->user->getPhone(),
  571. 'extra' => []
  572. ];
  573. $fieldValue = new ExtraFieldValue('user');
  574. $extraInfo = $fieldValue->getAllValuesForAnItem($this->user->getId(), true);
  575. foreach ($extraInfo as $extra) {
  576. /** @var ExtraFieldValues $extraValue */
  577. $extraValue = $extra['value'];
  578. $result['extra'][] = [
  579. 'title' => $extraValue->getField()->getDisplayText(true),
  580. 'value' => $extraValue->getValue()
  581. ];
  582. }
  583. return $result;
  584. }
  585. /**
  586. * @return array
  587. * @throws Exception
  588. */
  589. public function getCourseLearnPaths()
  590. {
  591. $sessionId = $this->session ? $this->session->getId() : 0;
  592. $categoriesTempList = learnpath::getCategories($this->course->getId());
  593. $categoryNone = new \Chamilo\CourseBundle\Entity\CLpCategory();
  594. $categoryNone->setId(0);
  595. $categoryNone->setName(get_lang('WithOutCategory'));
  596. $categoryNone->setPosition(0);
  597. $categories = array_merge([$categoryNone], $categoriesTempList);
  598. $categoryData = array();
  599. /** @var CLpCategory $category */
  600. foreach ($categories as $category) {
  601. $learnPathList = new LearnpathList(
  602. $this->user->getId(),
  603. $this->course->getCode(),
  604. $sessionId,
  605. null,
  606. false,
  607. $category->getId()
  608. );
  609. $flatLpList = $learnPathList->get_flat_list();
  610. if (empty($flatLpList)) {
  611. continue;
  612. }
  613. $listData = array();
  614. foreach ($flatLpList as $lpId => $lpDetails) {
  615. if ($lpDetails['lp_visibility'] == 0) {
  616. continue;
  617. }
  618. if (!learnpath::is_lp_visible_for_student(
  619. $lpId,
  620. $this->user->getId(),
  621. $this->course->getCode(),
  622. $sessionId
  623. )) {
  624. continue;
  625. }
  626. $timeLimits = false;
  627. //This is an old LP (from a migration 1.8.7) so we do nothing
  628. if (empty($lpDetails['created_on']) && empty($lpDetails['modified_on'])) {
  629. $timeLimits = false;
  630. }
  631. //Checking if expired_on is ON
  632. if (!empty($lpDetails['expired_on'])) {
  633. $timeLimits = true;
  634. }
  635. if ($timeLimits) {
  636. if (!empty($lpDetails['publicated_on']) && !empty($lpDetails['expired_on'])) {
  637. $startTime = api_strtotime($lpDetails['publicated_on'], 'UTC');
  638. $endTime = api_strtotime($lpDetails['expired_on'], 'UTC');
  639. $now = time();
  640. $isActivedTime = false;
  641. if ($now > $startTime && $endTime > $now) {
  642. $isActivedTime = true;
  643. }
  644. if (!$isActivedTime) {
  645. continue;
  646. }
  647. }
  648. }
  649. $progress = learnpath::getProgress($lpId, $this->user->getId(), $this->course->getId(), $sessionId);
  650. $listData[] = array(
  651. 'id' => $lpId,
  652. 'title' => Security::remove_XSS($lpDetails['lp_name']),
  653. 'progress' => intval($progress),
  654. 'url' => api_get_path(WEB_CODE_PATH).'webservices/api/v2.php?'.http_build_query([
  655. 'hash' => $this->encodeParams([
  656. 'action' => 'course_learnpath',
  657. 'lp_id' => $lpId,
  658. 'course' => $this->course->getId(),
  659. 'session' => $sessionId
  660. ])
  661. ])
  662. );
  663. }
  664. if (empty($listData)) {
  665. continue;
  666. }
  667. $categoryData[] = array(
  668. 'id' => $category->getId(),
  669. 'name' => $category->getName(),
  670. 'learnpaths' => $listData
  671. );
  672. }
  673. return $categoryData;
  674. }
  675. /**
  676. * @param array $additionalParams Optional
  677. * @return string
  678. */
  679. private function encodeParams(array $additionalParams = [])
  680. {
  681. $params = array_merge($additionalParams, [
  682. 'api_key' => $this->apiKey,
  683. 'username' => $this->user->getUsername(),
  684. ]);
  685. $strParams = serialize($params);
  686. $b64Encoded = base64_encode($strParams);
  687. return str_replace(['+', '/', '='], ['-', '_', '.'], $b64Encoded);
  688. }
  689. /**
  690. * @param string $encoded
  691. * @return array
  692. */
  693. public static function decodeParams($encoded) {
  694. $decoded = str_replace(['-', '_', '.'], ['+', '/', '='], $encoded);
  695. $mod4 = strlen($decoded) % 4;
  696. if ($mod4) {
  697. $decoded .= substr('====', $mod4);
  698. }
  699. $b64Decoded = base64_decode($decoded);
  700. return unserialize($b64Decoded);
  701. }
  702. /**
  703. * Start login for a user. Then make a redirect to show the learnpath
  704. * @param int $lpId
  705. */
  706. public function showLearningPath($lpId)
  707. {
  708. $loggedUser['user_id'] = $this->user->getId();
  709. $loggedUser['status'] = $this->user->getStatus();
  710. $loggedUser['uidReset'] = true;
  711. $sessionId = $this->session ? $this->session->getId() : 0;
  712. ChamiloSession::write('_user', $loggedUser);
  713. Login::init_user($this->user->getId(), true);
  714. $url = api_get_path(WEB_CODE_PATH).'lp/lp_controller.php?'.http_build_query([
  715. 'cidReq' => $this->course->getCode(),
  716. 'id_session' => $sessionId,
  717. 'gidReq' => 0,
  718. 'gradebook' => 0,
  719. 'origin' => '',
  720. 'action' => 'view',
  721. 'lp_id' => intval($lpId),
  722. 'isStudentView' => 'true'
  723. ]);
  724. header("Location: $url");
  725. exit;
  726. }
  727. /**
  728. * @param array $postValues
  729. * @param int $forumId
  730. * @return array
  731. */
  732. public function saveForumPost(array $postValues, $forumId)
  733. {
  734. require_once api_get_path(SYS_CODE_PATH).'forum/forumfunction.inc.php';
  735. $forum = get_forums($forumId, $this->course->getCode());
  736. store_reply($forum, $postValues, $this->course->getId(), $this->user->getId());
  737. return [
  738. 'registered' => true
  739. ];
  740. }
  741. /**
  742. * Get the list of sessions for current user
  743. * @return array the sessions list
  744. */
  745. public function getUserSessions()
  746. {
  747. $data = [];
  748. $sessionsByCategory = UserManager::get_sessions_by_category($this->user->getId(), false);
  749. foreach ($sessionsByCategory as $category) {
  750. $categorySessions = [];
  751. foreach ($category['sessions'] as $sessions) {
  752. $sessionCourses = [];
  753. foreach ($sessions['courses'] as $course) {
  754. $courseInfo = api_get_course_info_by_id($course['real_id']);
  755. $teachers = SessionManager::getCoachesByCourseSessionToString(
  756. $sessions['session_id'],
  757. $course['real_id']
  758. );
  759. $sessionCourses[] = [
  760. 'id' => $courseInfo['real_id'],
  761. 'title' => $courseInfo['title'],
  762. 'code' => $courseInfo['code'],
  763. 'directory' => $courseInfo['directory'],
  764. 'pictureUrl' => $courseInfo['course_image_large'],
  765. 'teachers' => $teachers
  766. ];
  767. }
  768. $sessionBox = Display::get_session_title_box($sessions['session_id']);
  769. $categorySessions[] = [
  770. 'name' => $sessionBox['title'],
  771. 'id' => $sessions['session_id'],
  772. 'date' => $sessionBox['dates'],
  773. 'duration' => isset($sessionBox['duration']) ? $sessionBox['duration'] : null,
  774. 'courses' => $sessionCourses
  775. ];
  776. }
  777. $data[] = [
  778. 'id' => $category['session_category']['id'],
  779. 'name' => $category['session_category']['name'],
  780. 'sessions' => $categorySessions
  781. ];
  782. }
  783. return $data;
  784. }
  785. /**
  786. * @param string $subject
  787. * @param string $text
  788. * @param array $receivers
  789. * @return array
  790. */
  791. public function saveUserMessage($subject, $text, array $receivers)
  792. {
  793. foreach ($receivers as $userId) {
  794. MessageManager::send_message($userId, $subject, $text);
  795. }
  796. return [
  797. 'sent' => true
  798. ];
  799. }
  800. /**
  801. * @param string $search
  802. * @return array
  803. */
  804. public function getMessageUsers($search)
  805. {
  806. /** @var UserRepository $repo */
  807. $repo = Database::getManager()
  808. ->getRepository('ChamiloUserBundle:User');
  809. $users = $repo->findUsersToSendMessage($this->user->getId(), $search);
  810. $showEmail = api_get_setting('show_email_addresses') === 'true';
  811. $data = [];
  812. /** @var User $user */
  813. foreach ($users as $user) {
  814. $userName = $user->getCompleteName();
  815. if ($showEmail) {
  816. $userName .= " ({$user->getEmail()})";
  817. }
  818. $data[] = [
  819. 'id' => $user->getId(),
  820. 'name' => $userName,
  821. ];
  822. }
  823. return $data;
  824. }
  825. /**
  826. * @param string $title
  827. * @param string $text
  828. * @return bool
  829. */
  830. public function saveCourseNotebook($title, $text)
  831. {
  832. $values = ['note_title' => $title, 'note_comment' => $text];
  833. $sessionId = $this->session ? $this->session->getId() : 0;
  834. $noteBookId = NotebookManager::save_note(
  835. $values,
  836. $this->user->getId(),
  837. $this->course->getId(),
  838. $sessionId
  839. );
  840. return [
  841. 'registered' => $noteBookId
  842. ];
  843. }
  844. /**
  845. * @param array $values
  846. * @param int $forumId
  847. * @return array
  848. */
  849. public function saveForumThread(array $values, $forumId)
  850. {
  851. require_once api_get_path(SYS_CODE_PATH).'forum/forumfunction.inc.php';
  852. $sessionId = $this->session ? $this->session->getId() : 0;
  853. $forum = get_forums($forumId, $this->course->getCode(), true, $sessionId);
  854. $courseInfo = api_get_course_info($this->course->getCode());
  855. $id = store_thread($forum, $values, $courseInfo, false, $this->user->getId(), $sessionId);
  856. return [
  857. 'registered' => $id
  858. ];
  859. }
  860. }