Rest.php 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007
  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($this->user->getId(), $this->course->getId(), $sessionId);
  370. $agenda->setType('course');
  371. $result = $agenda->parseAgendaFilter(null);
  372. $start = new DateTime(api_get_utc_datetime(), new DateTimeZone('UTC'));
  373. $start->modify('first day of this month');
  374. $start->setTime(0, 0, 0);
  375. $end = new DateTime(api_get_utc_datetime(), new DateTimeZone('UTC'));
  376. $end->modify('last day of this month');
  377. $end->setTime(23, 59, 59);
  378. $groupId = current($result['groups']);
  379. $userId = current($result['users']);
  380. $events = $agenda->getEvents(
  381. $start->getTimestamp(),
  382. $end->getTimestamp(),
  383. $this->course->getId(),
  384. $groupId,
  385. $userId,
  386. 'array'
  387. );
  388. if (!is_array($events)) {
  389. return [];
  390. }
  391. $webPath = api_get_path(WEB_PATH);
  392. return array_map(
  393. function ($event) use ($webPath) {
  394. return [
  395. 'id' => intval($event['unique_id']),
  396. 'title' => $event['title'],
  397. 'content' => str_replace('src="/', 'src="' . $webPath, $event['description']),
  398. 'startDate' => $event['start_date_localtime'],
  399. 'endDate' => $event['end_date_localtime'],
  400. 'isAllDay' => $event['allDay'] ? true : false
  401. ];
  402. },
  403. $events
  404. );
  405. }
  406. /**
  407. * @return array
  408. * @throws Exception
  409. */
  410. public function getCourseNotebooks()
  411. {
  412. $em = Database::getManager();
  413. /** @var CNotebookRepository $notebooksRepo */
  414. $notebooksRepo = $em->getRepository('ChamiloCourseBundle:CNotebook');
  415. $notebooks = $notebooksRepo->findByUser($this->user, $this->course, $this->session);
  416. return array_map(
  417. function (\Chamilo\CourseBundle\Entity\CNotebook $notebook) {
  418. return [
  419. 'id' => $notebook->getIid(),
  420. 'title' => $notebook->getTitle(),
  421. 'description' => $notebook->getDescription(),
  422. 'creationDate' => api_format_date(
  423. $notebook->getCreationDate()->getTimestamp()
  424. ),
  425. 'updateDate' => api_format_date(
  426. $notebook->getUpdateDate()->getTimestamp()
  427. )
  428. ];
  429. },
  430. $notebooks
  431. );
  432. }
  433. /**
  434. * @return array
  435. * @throws Exception
  436. */
  437. public function getCourseForumCategories()
  438. {
  439. $sessionId = $this->session ? $this->session->getId() : 0;
  440. $webCoursePath = api_get_path(WEB_COURSE_PATH) . $this->course->getDirectory() . '/upload/forum/images/';
  441. require_once api_get_path(SYS_CODE_PATH) . 'forum/forumfunction.inc.php';
  442. $categoriesFullData = get_forum_categories('', $this->course->getId(), $sessionId);
  443. $categories = [];
  444. $includeGroupsForums = api_get_setting('display_groups_forum_in_general_tool') === 'true';
  445. $forumsFullData = get_forums('', $this->course->getCode(), $includeGroupsForums, $sessionId);
  446. $forums = [];
  447. foreach ($forumsFullData as $forumId => $forumInfo) {
  448. $forum = [
  449. 'id' => intval($forumInfo['iid']),
  450. 'catId' => intval($forumInfo['forum_category']),
  451. 'title' => $forumInfo['forum_title'],
  452. 'description' => $forumInfo['forum_comment'],
  453. 'image' => $forumInfo['forum_image'] ? ($webCoursePath . $forumInfo['forum_image']) : '',
  454. 'numberOfThreads' => isset($forumInfo['number_of_threads']) ? intval($forumInfo['number_of_threads']) : 0,
  455. 'lastPost' => null
  456. ];
  457. $lastPostInfo = get_last_post_information($forumId, false, $this->course->getId());
  458. if ($lastPostInfo) {
  459. $forum['lastPost'] = [
  460. 'date' => api_convert_and_format_date($lastPostInfo['last_post_date']),
  461. 'user' => api_get_person_name(
  462. $lastPostInfo['last_poster_firstname'],
  463. $lastPostInfo['last_poster_lastname']
  464. )
  465. ];
  466. }
  467. $forums[] = $forum;
  468. }
  469. foreach ($categoriesFullData as $category) {
  470. $categoryForums = array_filter(
  471. $forums,
  472. function (array $forum) use ($category) {
  473. if ($forum['catId'] != $category['cat_id']) {
  474. return false;
  475. }
  476. return true;
  477. }
  478. );
  479. $categories[] = [
  480. 'id' => intval($category['iid']),
  481. 'title' => $category['cat_title'],
  482. 'catId' => intval($category['cat_id']),
  483. 'description' => $category['cat_comment'],
  484. 'forums' => $categoryForums,
  485. 'courseId' => $this->course->getId()
  486. ];
  487. }
  488. return $categories;
  489. }
  490. /**
  491. * @param int $forumId
  492. * @return array
  493. * @throws Exception
  494. */
  495. public function getCourseForum($forumId)
  496. {
  497. require_once api_get_path(SYS_CODE_PATH) . 'forum/forumfunction.inc.php';
  498. $forumInfo = get_forums($forumId, $this->course->getCode());
  499. if (!isset($forumInfo['iid'])) {
  500. throw new Exception(get_lang('NoForum'));
  501. }
  502. $webCoursePath = api_get_path(WEB_COURSE_PATH) . $this->course->getDirectory() . '/upload/forum/images/';
  503. $forum = [
  504. 'id' => $forumInfo['iid'],
  505. 'title' => $forumInfo['forum_title'],
  506. 'description' => $forumInfo['forum_comment'],
  507. 'image' => $forumInfo['forum_image'] ? ($webCoursePath . $forumInfo['forum_image']) : '',
  508. 'threads' => []
  509. ];
  510. $threads = get_threads($forumInfo['iid'], $this->course->getId());
  511. foreach ($threads as $thread) {
  512. $forum['threads'][] = [
  513. 'id' => $thread['iid'],
  514. 'title' => $thread['thread_title'],
  515. 'lastEditDate' => api_convert_and_format_date($thread['lastedit_date'], DATE_TIME_FORMAT_LONG_24H),
  516. 'numberOfReplies' => $thread['thread_replies'],
  517. 'numberOfViews' => $thread['thread_views'],
  518. 'author' => api_get_person_name($thread['firstname'], $thread['lastname'])
  519. ];
  520. }
  521. return $forum;
  522. }
  523. /**
  524. * @param int $forumId
  525. * @param int $threadId
  526. * @return array
  527. */
  528. public function getCourseForumThread($forumId, $threadId)
  529. {
  530. require_once api_get_path(SYS_CODE_PATH) . 'forum/forumfunction.inc.php';
  531. $threadInfo = get_thread_information($forumId, $threadId);
  532. $thread = [
  533. 'id' => intval($threadInfo['iid']),
  534. 'cId' => intval($threadInfo['c_id']),
  535. 'title' => $threadInfo['thread_title'],
  536. 'forumId' => intval($threadInfo['forum_id']),
  537. 'posts' => []
  538. ];
  539. $forumInfo = get_forums($threadInfo['forum_id'], $this->course->getCode());
  540. $postsInfo = getPosts($forumInfo, $threadInfo['iid'], 'ASC');
  541. foreach ($postsInfo as $postInfo) {
  542. $thread['posts'][] = [
  543. 'id' => $postInfo['iid'],
  544. 'title' => $postInfo['post_title'],
  545. 'text' => $postInfo['post_text'],
  546. 'author' => api_get_person_name($postInfo['firstname'], $postInfo['lastname']),
  547. 'date' => api_convert_and_format_date($postInfo['post_date'], DATE_TIME_FORMAT_LONG_24H),
  548. 'parentId' => $postInfo['post_parent_id']
  549. ];
  550. }
  551. return $thread;
  552. }
  553. /**
  554. * @return array
  555. */
  556. public function getUserProfile()
  557. {
  558. $pictureInfo = UserManager::get_user_picture_path_by_id($this->user->getId(), 'web');
  559. $result = [
  560. 'pictureUri' => $pictureInfo['dir'] . $pictureInfo['file'],
  561. 'fullName' => $this->user->getCompleteName(),
  562. 'username' => $this->user->getUsername(),
  563. 'officialCode' => $this->user->getOfficialCode(),
  564. 'phone' => $this->user->getPhone(),
  565. 'extra' => []
  566. ];
  567. $fieldValue = new ExtraFieldValue('user');
  568. $extraInfo = $fieldValue->getAllValuesForAnItem($this->user->getId(), true);
  569. foreach ($extraInfo as $extra) {
  570. /** @var ExtraFieldValues $extraValue */
  571. $extraValue = $extra['value'];
  572. $result['extra'][] = [
  573. 'title' => $extraValue->getField()->getDisplayText(true),
  574. 'value' => $extraValue->getValue()
  575. ];
  576. }
  577. return $result;
  578. }
  579. /**
  580. * @return array
  581. * @throws Exception
  582. */
  583. public function getCourseLearnPaths()
  584. {
  585. $sessionId = $this->session ? $this->session->getId() : 0;
  586. $categoriesTempList = learnpath::getCategories($this->course->getId());
  587. $categoryNone = new \Chamilo\CourseBundle\Entity\CLpCategory();
  588. $categoryNone->setId(0);
  589. $categoryNone->setName(get_lang('WithOutCategory'));
  590. $categoryNone->setPosition(0);
  591. $categories = array_merge([$categoryNone], $categoriesTempList);
  592. $categoryData = array();
  593. /** @var CLpCategory $category */
  594. foreach ($categories as $category) {
  595. $learnPathList = new LearnpathList(
  596. $this->user->getId(),
  597. $this->course->getCode(),
  598. $sessionId,
  599. null,
  600. false,
  601. $category->getId()
  602. );
  603. $flatLpList = $learnPathList->get_flat_list();
  604. if (empty($flatLpList)) {
  605. continue;
  606. }
  607. $listData = array();
  608. foreach ($flatLpList as $lpId => $lpDetails) {
  609. if ($lpDetails['lp_visibility'] == 0) {
  610. continue;
  611. }
  612. if (!learnpath::is_lp_visible_for_student(
  613. $lpId,
  614. $this->user->getId(),
  615. $this->course->getCode(),
  616. $sessionId
  617. )) {
  618. continue;
  619. }
  620. $timeLimits = false;
  621. //This is an old LP (from a migration 1.8.7) so we do nothing
  622. if (empty($lpDetails['created_on']) && empty($lpDetails['modified_on'])) {
  623. $timeLimits = false;
  624. }
  625. //Checking if expired_on is ON
  626. if (!empty($lpDetails['expired_on'])) {
  627. $timeLimits = true;
  628. }
  629. if ($timeLimits) {
  630. if (!empty($lpDetails['publicated_on']) && !empty($lpDetails['expired_on'])) {
  631. $startTime = api_strtotime($lpDetails['publicated_on'], 'UTC');
  632. $endTime = api_strtotime($lpDetails['expired_on'], 'UTC');
  633. $now = time();
  634. $isActivedTime = false;
  635. if ($now > $startTime && $endTime > $now) {
  636. $isActivedTime = true;
  637. }
  638. if (!$isActivedTime) {
  639. continue;
  640. }
  641. }
  642. }
  643. $progress = learnpath::getProgress($lpId, $this->user->getId(), $this->course->getId(), $sessionId);
  644. $listData[] = array(
  645. 'id' => $lpId,
  646. 'title' => Security::remove_XSS($lpDetails['lp_name']),
  647. 'progress' => intval($progress),
  648. 'url' => api_get_path(WEB_CODE_PATH) . 'webservices/api/v2.php?' . http_build_query([
  649. 'hash' => $this->encodeParams([
  650. 'action' => 'course_learnpath',
  651. 'lp_id' => $lpId,
  652. 'course' => $this->course->getId(),
  653. 'session' => $sessionId
  654. ])
  655. ])
  656. );
  657. }
  658. if (empty($listData)) {
  659. continue;
  660. }
  661. $categoryData[] = array(
  662. 'id' => $category->getId(),
  663. 'name' => $category->getName(),
  664. 'learnpaths' => $listData
  665. );
  666. }
  667. return $categoryData;
  668. }
  669. /**
  670. * @param array $additionalParams Optional
  671. * @return string
  672. */
  673. private function encodeParams(array $additionalParams = [])
  674. {
  675. $params = array_merge($additionalParams, [
  676. 'api_key' => $this->apiKey,
  677. 'username' => $this->user->getUsername(),
  678. ]);
  679. $strParams = serialize($params);
  680. $b64Encoded = base64_encode($strParams);
  681. return str_replace(['+', '/', '='], ['-', '_', '.'], $b64Encoded);
  682. }
  683. /**
  684. * @param string $encoded
  685. * @return array
  686. */
  687. public static function decodeParams($encoded){
  688. $decoded = str_replace(['-', '_', '.'], ['+', '/', '='], $encoded);
  689. $mod4 = strlen($decoded) % 4;
  690. if ($mod4) {
  691. $decoded .= substr('====', $mod4);
  692. }
  693. $b64Decoded = base64_decode($decoded);
  694. return unserialize($b64Decoded);
  695. }
  696. /**
  697. * Start login for a user. Then make a redirect to show the learnpath
  698. * @param int $lpId
  699. */
  700. public function showLearningPath($lpId)
  701. {
  702. $loggedUser['user_id'] = $this->user->getId();
  703. $loggedUser['status'] = $this->user->getStatus();
  704. $loggedUser['uidReset'] = true;
  705. $sessionId = $this->session ? $this->session->getId() : 0;
  706. ChamiloSession::write('_user', $loggedUser);
  707. Login::init_user($this->user->getId(), true);
  708. $url = api_get_path(WEB_CODE_PATH) . 'lp/lp_controller.php?' . http_build_query([
  709. 'cidReq' => $this->course->getCode(),
  710. 'id_session' => $sessionId,
  711. 'gidReq' => 0,
  712. 'gradebook' => 0,
  713. 'origin' => '',
  714. 'action' => 'view',
  715. 'lp_id' => intval($lpId),
  716. 'isStudentView' => 'true'
  717. ]);
  718. header("Location: $url");
  719. exit;
  720. }
  721. /**
  722. * @param array $postValues
  723. * @param int $forumId
  724. * @return array
  725. */
  726. public function saveForumPost(array $postValues, $forumId)
  727. {
  728. require_once api_get_path(SYS_CODE_PATH) . 'forum/forumfunction.inc.php';
  729. $forum = get_forums($forumId, $this->course->getCode());
  730. store_reply($forum, $postValues, $this->course->getId(), $this->user->getId());
  731. return [
  732. 'registered' => true
  733. ];
  734. }
  735. /**
  736. * Get the list of sessions for current user
  737. * @return array the sessions list
  738. */
  739. public function getUserSessions()
  740. {
  741. $data = [];
  742. $sessionsByCategory = UserManager::get_sessions_by_category($this->user->getId(), false);
  743. foreach ($sessionsByCategory as $category) {
  744. $categorySessions = [];
  745. foreach ($category['sessions'] as $sessions) {
  746. $sessionCourses = [];
  747. foreach ($sessions['courses'] as $course) {
  748. $courseInfo = api_get_course_info_by_id($course['real_id']);
  749. $sessionCourses[] = [
  750. 'visibility' => $course['visibility'],
  751. 'status' => $course['status'],
  752. 'id' => $courseInfo['real_id'],
  753. 'title' => $courseInfo['title'],
  754. 'code' => $courseInfo['code'],
  755. 'directory' => $courseInfo['directory'],
  756. 'pictureUrl' => $courseInfo['course_image_large']
  757. ];
  758. }
  759. $categorySessions[] = [
  760. 'session_name' => $sessions['session_name'],
  761. 'session_id' => $sessions['session_id'],
  762. 'accessStartDate' => api_format_date($sessions['access_start_date'], DATE_TIME_FORMAT_SHORT),
  763. 'accessEndDate' => api_format_date($sessions['access_end_date'], DATE_TIME_FORMAT_SHORT),
  764. 'courses' => $sessionCourses
  765. ];
  766. }
  767. $data[] = [
  768. 'id' => $category['session_category']['id'],
  769. 'name' => $category['session_category']['name'],
  770. 'sessions' => $categorySessions
  771. ];
  772. }
  773. return $data;
  774. }
  775. /**
  776. * @param string $subject
  777. * @param string $text
  778. * @param array $receivers
  779. * @return array
  780. */
  781. public function saveUserMessage($subject, $text, array $receivers)
  782. {
  783. foreach ($receivers as $userId) {
  784. MessageManager::send_message($userId, $subject, $text);
  785. }
  786. return [
  787. 'sent' => true
  788. ];
  789. }
  790. /**
  791. * @param string $search
  792. * @return array
  793. */
  794. public function getMessageUsers($search)
  795. {
  796. /** @var UserRepository $repo */
  797. $repo = Database::getManager()
  798. ->getRepository('ChamiloUserBundle:User');
  799. $users = $repo->findUsersToSendMessage($this->user->getId(), $search);
  800. $showEmail = api_get_setting('show_email_addresses') === 'true';
  801. $data = [];
  802. /** @var User $user */
  803. foreach ($users as $user) {
  804. $userName = $user->getCompleteName();
  805. if ($showEmail) {
  806. $userName .= " ({$user->getEmail()})";
  807. }
  808. $data[] = [
  809. 'id' => $user->getId(),
  810. 'name' => $userName,
  811. ];
  812. }
  813. return $data;
  814. }
  815. /**
  816. * @param string $title
  817. * @param string $text
  818. * @return bool
  819. */
  820. public function saveCourseNotebook($title, $text)
  821. {
  822. $values = ['note_title' => $title, 'note_comment' => $text];
  823. $sessionId = $this->session ? $this->session->getId() : 0;
  824. $noteBookId = NotebookManager::save_note(
  825. $values,
  826. $this->user->getId(),
  827. $this->course->getId(),
  828. $sessionId
  829. );
  830. return [
  831. 'registered' => $noteBookId
  832. ];
  833. }
  834. /**
  835. * @param array $values
  836. * @param int $forumId
  837. * @return array
  838. */
  839. public function saveForumThread(array $values, $forumId)
  840. {
  841. require_once api_get_path(SYS_CODE_PATH) . 'forum/forumfunction.inc.php';
  842. $forum = get_forums($forumId, $this->course->getCode());
  843. $courseInfo = api_get_course_info($this->course->getCode());
  844. $sessionId = $this->session ? $this->session->getId() : 0;
  845. $id = store_thread($forum, $values, $courseInfo, false, $this->user->getId(), $sessionId);
  846. return [
  847. 'registered' => $id
  848. ];
  849. }
  850. }