Rest.php 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996
  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. return [
  196. 'id' => $this->course->getId(),
  197. 'title' => $this->course->getTitle(),
  198. 'code' => $this->course->getCode(),
  199. 'directory' => $this->course->getDirectory(),
  200. 'urlPicture' => $this->course->getPicturePath(true),
  201. 'teachers' => $teachers
  202. ];
  203. }
  204. /**
  205. * Get the course descriptions
  206. * @return array
  207. * @throws Exception
  208. */
  209. public function getCourseDescriptions()
  210. {
  211. $descriptions = CourseDescription::get_descriptions($this->course->getId());
  212. $results = [];
  213. /** @var CourseDescription $description */
  214. foreach ($descriptions as $description) {
  215. $results[] = [
  216. 'id' => $description->get_description_type(),
  217. 'title' => $description->get_title(),
  218. 'content' => str_replace('src="/', 'src="' . api_get_path(WEB_PATH), $description->get_content())
  219. ];
  220. }
  221. return $results;
  222. }
  223. /**
  224. * @param int $directoryId
  225. * @return array
  226. * @throws Exception
  227. */
  228. public function getCourseDocuments($directoryId = 0)
  229. {
  230. /** @var string $path */
  231. $path = '/';
  232. $sessionId = $this->session ? $this->session->getId() : 0;
  233. if ($directoryId) {
  234. $directory = DocumentManager::get_document_data_by_id(
  235. $directoryId,
  236. $this->course->getCode(),
  237. false,
  238. $sessionId
  239. );
  240. if (!$directory) {
  241. throw new Exception('NoDataAvailable');
  242. }
  243. $path = $directory['path'];
  244. }
  245. require_once api_get_path(LIBRARY_PATH) . 'fileDisplay.lib.php';
  246. $courseInfo = api_get_course_info_by_id($this->course->getId());
  247. $documents = DocumentManager::get_all_document_data(
  248. $courseInfo,
  249. $path,
  250. 0,
  251. null,
  252. false,
  253. false,
  254. $sessionId
  255. );
  256. $results = [];
  257. if (is_array($documents)) {
  258. $webPath = api_get_path(WEB_CODE_PATH) . 'document/document.php?';
  259. /** @var array $document */
  260. foreach ($documents as $document) {
  261. if ($document['visibility'] != '1') {
  262. continue;
  263. }
  264. $icon = $document['filetype'] == 'file'
  265. ? choose_image($document['path'])
  266. : chooseFolderIcon($document['path']);
  267. $results[] = [
  268. 'id' => $document['id'],
  269. 'type' => $document['filetype'],
  270. 'title' => $document['title'],
  271. 'path' => $document['path'],
  272. 'url' => $webPath . http_build_query([
  273. 'username' => $this->user->getUsername(),
  274. 'api_key' => $this->apiKey,
  275. 'cidReq' => $this->course->getCode(),
  276. 'id_session' => $sessionId,
  277. 'gidReq' => 0,
  278. 'gradebook' => 0,
  279. 'origin' => '',
  280. 'action' => 'download',
  281. 'id' => $document['id']
  282. ]),
  283. 'icon' => $icon,
  284. 'size' => format_file_size($document['size'])
  285. ];
  286. }
  287. }
  288. return $results;
  289. }
  290. /**
  291. * @param int $courseId
  292. * @return array
  293. * @throws Exception
  294. */
  295. public function getCourseAnnouncements()
  296. {
  297. $sessionId = $this->session ? $this->session->getId() : 0;
  298. $announcements = AnnouncementManager::getAnnouncements(
  299. null,
  300. null,
  301. false,
  302. null,
  303. null,
  304. null,
  305. null,
  306. null,
  307. 0,
  308. $this->user->getId(),
  309. $this->course->getId(),
  310. $sessionId
  311. );
  312. $announcements = array_map(function ($announcement) {
  313. return [
  314. 'id' => intval($announcement['id']),
  315. 'title' => strip_tags($announcement['title']),
  316. 'creatorName' => strip_tags($announcement['username']),
  317. 'date' => strip_tags($announcement['insert_date'])
  318. ];
  319. }, $announcements);
  320. return $announcements;
  321. }
  322. /**
  323. * @param int $announcementId
  324. * @return array
  325. * @throws Exception
  326. */
  327. public function getCourseAnnouncement($announcementId)
  328. {
  329. $sessionId = $this->session ? $this->session->getId() : 0;
  330. $announcement = AnnouncementManager::getAnnouncementInfoById(
  331. $announcementId,
  332. $this->course->getId(),
  333. $this->user->getId()
  334. );
  335. if (!$announcement) {
  336. throw new Exception(get_lang('NoAnnouncement'));
  337. }
  338. return [
  339. 'id' => intval($announcement['announcement']->getIid()),
  340. 'title' => $announcement['announcement']->getTitle(),
  341. 'creatorName' => $announcement['item_property']->getInsertUser()->getCompleteName(),
  342. 'date' => api_convert_and_format_date($announcement['item_property']->getInsertDate(), DATE_TIME_FORMAT_LONG_24H),
  343. 'content' => AnnouncementManager::parse_content(
  344. $this->user->getId(),
  345. $announcement['announcement']->getContent(),
  346. $this->course->getCode(),
  347. $sessionId
  348. )
  349. ];
  350. }
  351. /**
  352. * @return array
  353. * @throws Exception
  354. */
  355. public function getCourseAgenda()
  356. {
  357. $sessionId = $this->session ? $this->session->getId() : 0;
  358. $agenda = new Agenda($this->user->getId(), $this->course->getId(), $sessionId);
  359. $agenda->setType('course');
  360. $result = $agenda->parseAgendaFilter(null);
  361. $start = new DateTime(api_get_utc_datetime(), new DateTimeZone('UTC'));
  362. $start->modify('first day of this month');
  363. $start->setTime(0, 0, 0);
  364. $end = new DateTime(api_get_utc_datetime(), new DateTimeZone('UTC'));
  365. $end->modify('last day of this month');
  366. $end->setTime(23, 59, 59);
  367. $groupId = current($result['groups']);
  368. $userId = current($result['users']);
  369. $events = $agenda->getEvents(
  370. $start->getTimestamp(),
  371. $end->getTimestamp(),
  372. $this->course->getId(),
  373. $groupId,
  374. $userId,
  375. 'array'
  376. );
  377. if (!is_array($events)) {
  378. return [];
  379. }
  380. $webPath = api_get_path(WEB_PATH);
  381. return array_map(
  382. function ($event) use ($webPath) {
  383. return [
  384. 'id' => intval($event['unique_id']),
  385. 'title' => $event['title'],
  386. 'content' => str_replace('src="/', 'src="' . $webPath, $event['description']),
  387. 'startDate' => $event['start_date_localtime'],
  388. 'endDate' => $event['end_date_localtime'],
  389. 'isAllDay' => $event['allDay'] ? true : false
  390. ];
  391. },
  392. $events
  393. );
  394. }
  395. /**
  396. * @return array
  397. * @throws Exception
  398. */
  399. public function getCourseNotebooks()
  400. {
  401. $em = Database::getManager();
  402. /** @var CNotebookRepository $notebooksRepo */
  403. $notebooksRepo = $em->getRepository('ChamiloCourseBundle:CNotebook');
  404. $notebooks = $notebooksRepo->findByUser($this->user, $this->course, $this->session);
  405. return array_map(
  406. function (\Chamilo\CourseBundle\Entity\CNotebook $notebook) {
  407. return [
  408. 'id' => $notebook->getIid(),
  409. 'title' => $notebook->getTitle(),
  410. 'description' => $notebook->getDescription(),
  411. 'creationDate' => api_format_date(
  412. $notebook->getCreationDate()->getTimestamp()
  413. ),
  414. 'updateDate' => api_format_date(
  415. $notebook->getUpdateDate()->getTimestamp()
  416. )
  417. ];
  418. },
  419. $notebooks
  420. );
  421. }
  422. /**
  423. * @return array
  424. * @throws Exception
  425. */
  426. public function getCourseForumCategories()
  427. {
  428. $sessionId = $this->session ? $this->session->getId() : 0;
  429. $webCoursePath = api_get_path(WEB_COURSE_PATH) . $this->course->getDirectory() . '/upload/forum/images/';
  430. require_once api_get_path(SYS_CODE_PATH) . 'forum/forumfunction.inc.php';
  431. $categoriesFullData = get_forum_categories('', $this->course->getId(), $sessionId);
  432. $categories = [];
  433. $includeGroupsForums = api_get_setting('display_groups_forum_in_general_tool') === 'true';
  434. $forumsFullData = get_forums('', $this->course->getCode(), $includeGroupsForums, $sessionId);
  435. $forums = [];
  436. foreach ($forumsFullData as $forumId => $forumInfo) {
  437. $forum = [
  438. 'id' => intval($forumInfo['iid']),
  439. 'catId' => intval($forumInfo['forum_category']),
  440. 'title' => $forumInfo['forum_title'],
  441. 'description' => $forumInfo['forum_comment'],
  442. 'image' => $forumInfo['forum_image'] ? ($webCoursePath . $forumInfo['forum_image']) : '',
  443. 'numberOfThreads' => isset($forumInfo['number_of_threads']) ? intval($forumInfo['number_of_threads']) : 0,
  444. 'lastPost' => null
  445. ];
  446. $lastPostInfo = get_last_post_information($forumId, false, $this->course->getId());
  447. if ($lastPostInfo) {
  448. $forum['lastPost'] = [
  449. 'date' => api_convert_and_format_date($lastPostInfo['last_post_date']),
  450. 'user' => api_get_person_name(
  451. $lastPostInfo['last_poster_firstname'],
  452. $lastPostInfo['last_poster_lastname']
  453. )
  454. ];
  455. }
  456. $forums[] = $forum;
  457. }
  458. foreach ($categoriesFullData as $category) {
  459. $categoryForums = array_filter(
  460. $forums,
  461. function (array $forum) use ($category) {
  462. if ($forum['catId'] != $category['cat_id']) {
  463. return false;
  464. }
  465. return true;
  466. }
  467. );
  468. $categories[] = [
  469. 'id' => intval($category['iid']),
  470. 'title' => $category['cat_title'],
  471. 'catId' => intval($category['cat_id']),
  472. 'description' => $category['cat_comment'],
  473. 'forums' => $categoryForums,
  474. 'courseId' => $this->course->getId()
  475. ];
  476. }
  477. return $categories;
  478. }
  479. /**
  480. * @param int $forumId
  481. * @return array
  482. * @throws Exception
  483. */
  484. public function getCourseForum($forumId)
  485. {
  486. require_once api_get_path(SYS_CODE_PATH) . 'forum/forumfunction.inc.php';
  487. $forumInfo = get_forums($forumId, $this->course->getCode());
  488. if (!isset($forumInfo['iid'])) {
  489. throw new Exception(get_lang('NoForum'));
  490. }
  491. $webCoursePath = api_get_path(WEB_COURSE_PATH) . $this->course->getDirectory() . '/upload/forum/images/';
  492. $forum = [
  493. 'id' => $forumInfo['iid'],
  494. 'title' => $forumInfo['forum_title'],
  495. 'description' => $forumInfo['forum_comment'],
  496. 'image' => $forumInfo['forum_image'] ? ($webCoursePath . $forumInfo['forum_image']) : '',
  497. 'threads' => []
  498. ];
  499. $threads = get_threads($forumInfo['iid'], $this->course->getId());
  500. foreach ($threads as $thread) {
  501. $forum['threads'][] = [
  502. 'id' => $thread['iid'],
  503. 'title' => $thread['thread_title'],
  504. 'lastEditDate' => api_convert_and_format_date($thread['lastedit_date'], DATE_TIME_FORMAT_LONG_24H),
  505. 'numberOfReplies' => $thread['thread_replies'],
  506. 'numberOfViews' => $thread['thread_views'],
  507. 'author' => api_get_person_name($thread['firstname'], $thread['lastname'])
  508. ];
  509. }
  510. return $forum;
  511. }
  512. /**
  513. * @param int $forumId
  514. * @param int $threadId
  515. * @return array
  516. */
  517. public function getCourseForumThread($forumId, $threadId)
  518. {
  519. require_once api_get_path(SYS_CODE_PATH) . 'forum/forumfunction.inc.php';
  520. $threadInfo = get_thread_information($forumId, $threadId);
  521. $thread = [
  522. 'id' => intval($threadInfo['iid']),
  523. 'cId' => intval($threadInfo['c_id']),
  524. 'title' => $threadInfo['thread_title'],
  525. 'forumId' => intval($threadInfo['forum_id']),
  526. 'posts' => []
  527. ];
  528. $forumInfo = get_forums($threadInfo['forum_id'], $this->course->getCode());
  529. $postsInfo = getPosts($forumInfo, $threadInfo['iid'], 'ASC');
  530. foreach ($postsInfo as $postInfo) {
  531. $thread['posts'][] = [
  532. 'id' => $postInfo['iid'],
  533. 'title' => $postInfo['post_title'],
  534. 'text' => $postInfo['post_text'],
  535. 'author' => api_get_person_name($postInfo['firstname'], $postInfo['lastname']),
  536. 'date' => api_convert_and_format_date($postInfo['post_date'], DATE_TIME_FORMAT_LONG_24H),
  537. 'parentId' => $postInfo['post_parent_id']
  538. ];
  539. }
  540. return $thread;
  541. }
  542. /**
  543. * @return array
  544. */
  545. public function getUserProfile()
  546. {
  547. $pictureInfo = UserManager::get_user_picture_path_by_id($this->user->getId(), 'web');
  548. $result = [
  549. 'pictureUri' => $pictureInfo['dir'] . $pictureInfo['file'],
  550. 'fullName' => $this->user->getCompleteName(),
  551. 'username' => $this->user->getUsername(),
  552. 'officialCode' => $this->user->getOfficialCode(),
  553. 'phone' => $this->user->getPhone(),
  554. 'extra' => []
  555. ];
  556. $fieldValue = new ExtraFieldValue('user');
  557. $extraInfo = $fieldValue->getAllValuesForAnItem($this->user->getId(), true);
  558. foreach ($extraInfo as $extra) {
  559. /** @var ExtraFieldValues $extraValue */
  560. $extraValue = $extra['value'];
  561. $result['extra'][] = [
  562. 'title' => $extraValue->getField()->getDisplayText(true),
  563. 'value' => $extraValue->getValue()
  564. ];
  565. }
  566. return $result;
  567. }
  568. /**
  569. * @return array
  570. * @throws Exception
  571. */
  572. public function getCourseLearnPaths()
  573. {
  574. $sessionId = $this->session ? $this->session->getId() : 0;
  575. $categoriesTempList = learnpath::getCategories($this->course->getId());
  576. $categoryNone = new \Chamilo\CourseBundle\Entity\CLpCategory();
  577. $categoryNone->setId(0);
  578. $categoryNone->setName(get_lang('WithOutCategory'));
  579. $categoryNone->setPosition(0);
  580. $categories = array_merge([$categoryNone], $categoriesTempList);
  581. $categoryData = array();
  582. /** @var CLpCategory $category */
  583. foreach ($categories as $category) {
  584. $learnPathList = new LearnpathList(
  585. $this->user->getId(),
  586. $this->course->getCode(),
  587. $sessionId,
  588. null,
  589. false,
  590. $category->getId()
  591. );
  592. $flatLpList = $learnPathList->get_flat_list();
  593. if (empty($flatLpList)) {
  594. continue;
  595. }
  596. $listData = array();
  597. foreach ($flatLpList as $lpId => $lpDetails) {
  598. if ($lpDetails['lp_visibility'] == 0) {
  599. continue;
  600. }
  601. if (!learnpath::is_lp_visible_for_student(
  602. $lpId,
  603. $this->user->getId(),
  604. $this->course->getCode(),
  605. $sessionId
  606. )) {
  607. continue;
  608. }
  609. $timeLimits = false;
  610. //This is an old LP (from a migration 1.8.7) so we do nothing
  611. if (empty($lpDetails['created_on']) && empty($lpDetails['modified_on'])) {
  612. $timeLimits = false;
  613. }
  614. //Checking if expired_on is ON
  615. if (!empty($lpDetails['expired_on'])) {
  616. $timeLimits = true;
  617. }
  618. if ($timeLimits) {
  619. if (!empty($lpDetails['publicated_on']) && !empty($lpDetails['expired_on'])) {
  620. $startTime = api_strtotime($lpDetails['publicated_on'], 'UTC');
  621. $endTime = api_strtotime($lpDetails['expired_on'], 'UTC');
  622. $now = time();
  623. $isActivedTime = false;
  624. if ($now > $startTime && $endTime > $now) {
  625. $isActivedTime = true;
  626. }
  627. if (!$isActivedTime) {
  628. continue;
  629. }
  630. }
  631. }
  632. $progress = learnpath::getProgress($lpId, $this->user->getId(), $this->course->getId(), $sessionId);
  633. $listData[] = array(
  634. 'id' => $lpId,
  635. 'title' => Security::remove_XSS($lpDetails['lp_name']),
  636. 'progress' => intval($progress),
  637. 'url' => api_get_path(WEB_CODE_PATH) . 'webservices/api/v2.php?' . http_build_query([
  638. 'hash' => $this->encodeParams([
  639. 'action' => 'course_learnpath',
  640. 'lp_id' => $lpId,
  641. 'course' => $this->course->getId(),
  642. 'session' => $sessionId
  643. ])
  644. ])
  645. );
  646. }
  647. if (empty($listData)) {
  648. continue;
  649. }
  650. $categoryData[] = array(
  651. 'id' => $category->getId(),
  652. 'name' => $category->getName(),
  653. 'learnpaths' => $listData
  654. );
  655. }
  656. return $categoryData;
  657. }
  658. /**
  659. * @param array $additionalParams Optional
  660. * @return string
  661. */
  662. private function encodeParams(array $additionalParams = [])
  663. {
  664. $params = array_merge($additionalParams, [
  665. 'api_key' => $this->apiKey,
  666. 'username' => $this->user->getUsername(),
  667. ]);
  668. $strParams = serialize($params);
  669. $b64Encoded = base64_encode($strParams);
  670. return str_replace(['+', '/', '='], ['-', '_', '.'], $b64Encoded);
  671. }
  672. /**
  673. * @param string $encoded
  674. * @return array
  675. */
  676. public static function decodeParams($encoded){
  677. $decoded = str_replace(['-', '_', '.'], ['+', '/', '='], $encoded);
  678. $mod4 = strlen($decoded) % 4;
  679. if ($mod4) {
  680. $decoded .= substr('====', $mod4);
  681. }
  682. $b64Decoded = base64_decode($decoded);
  683. return unserialize($b64Decoded);
  684. }
  685. /**
  686. * Start login for a user. Then make a redirect to show the learnpath
  687. * @param int $lpId
  688. */
  689. public function showLearningPath($lpId)
  690. {
  691. $loggedUser['user_id'] = $this->user->getId();
  692. $loggedUser['status'] = $this->user->getStatus();
  693. $loggedUser['uidReset'] = true;
  694. $sessionId = $this->session ? $this->session->getId() : 0;
  695. ChamiloSession::write('_user', $loggedUser);
  696. Login::init_user($this->user->getId(), true);
  697. $url = api_get_path(WEB_CODE_PATH) . 'lp/lp_controller.php?' . http_build_query([
  698. 'cidReq' => $this->course->getCode(),
  699. 'id_session' => $sessionId,
  700. 'gidReq' => 0,
  701. 'gradebook' => 0,
  702. 'origin' => '',
  703. 'action' => 'view',
  704. 'lp_id' => intval($lpId),
  705. 'isStudentView' => 'true'
  706. ]);
  707. header("Location: $url");
  708. exit;
  709. }
  710. /**
  711. * @param array $postValues
  712. * @param int $forumId
  713. * @return array
  714. */
  715. public function saveForumPost(array $postValues, $forumId)
  716. {
  717. require_once api_get_path(SYS_CODE_PATH) . 'forum/forumfunction.inc.php';
  718. $forum = get_forums($forumId, $this->course->getCode());
  719. store_reply($forum, $postValues, $this->course->getId(), $this->user->getId());
  720. return [
  721. 'registered' => true
  722. ];
  723. }
  724. /**
  725. * Get the list of sessions for current user
  726. * @return array the sessions list
  727. */
  728. public function getUserSessions()
  729. {
  730. $data = [];
  731. $sessionsByCategory = UserManager::get_sessions_by_category($this->user->getId(), false);
  732. foreach ($sessionsByCategory as $category) {
  733. $categorySessions = [];
  734. foreach ($category['sessions'] as $sessions) {
  735. $sessionCourses = [];
  736. foreach ($sessions['courses'] as $course) {
  737. $courseInfo = api_get_course_info_by_id($course['real_id']);
  738. $sessionCourses[] = [
  739. 'visibility' => $course['visibility'],
  740. 'status' => $course['status'],
  741. 'id' => $courseInfo['real_id'],
  742. 'title' => $courseInfo['title'],
  743. 'code' => $courseInfo['code'],
  744. 'directory' => $courseInfo['directory'],
  745. 'pictureUrl' => $courseInfo['course_image_large']
  746. ];
  747. }
  748. $categorySessions[] = [
  749. 'session_name' => $sessions['session_name'],
  750. 'session_id' => $sessions['session_id'],
  751. 'accessStartDate' => api_format_date($sessions['access_start_date'], DATE_TIME_FORMAT_SHORT),
  752. 'accessEndDate' => api_format_date($sessions['access_end_date'], DATE_TIME_FORMAT_SHORT),
  753. 'courses' => $sessionCourses
  754. ];
  755. }
  756. $data[] = [
  757. 'id' => $category['session_category']['id'],
  758. 'name' => $category['session_category']['name'],
  759. 'sessions' => $categorySessions
  760. ];
  761. }
  762. return $data;
  763. }
  764. /**
  765. * @param string $subject
  766. * @param string $text
  767. * @param array $receivers
  768. * @return array
  769. */
  770. public function saveUserMessage($subject, $text, array $receivers)
  771. {
  772. foreach ($receivers as $userId) {
  773. MessageManager::send_message($userId, $subject, $text);
  774. }
  775. return [
  776. 'sent' => true
  777. ];
  778. }
  779. /**
  780. * @param string $search
  781. * @return array
  782. */
  783. public function getMessageUsers($search)
  784. {
  785. /** @var UserRepository $repo */
  786. $repo = Database::getManager()
  787. ->getRepository('ChamiloUserBundle:User');
  788. $users = $repo->findUsersToSendMessage($this->user->getId(), $search);
  789. $showEmail = api_get_setting('show_email_addresses') === 'true';
  790. $data = [];
  791. /** @var User $user */
  792. foreach ($users as $user) {
  793. $userName = $user->getCompleteName();
  794. if ($showEmail) {
  795. $userName .= " ({$user->getEmail()})";
  796. }
  797. $data[] = [
  798. 'id' => $user->getId(),
  799. 'name' => $userName,
  800. ];
  801. }
  802. return $data;
  803. }
  804. /**
  805. * @param string $title
  806. * @param string $text
  807. * @return bool
  808. */
  809. public function saveCourseNotebook($title, $text)
  810. {
  811. $values = ['note_title' => $title, 'note_comment' => $text];
  812. $sessionId = $this->session ? $this->session->getId() : 0;
  813. $noteBookId = NotebookManager::save_note(
  814. $values,
  815. $this->user->getId(),
  816. $this->course->getId(),
  817. $sessionId
  818. );
  819. return [
  820. 'registered' => $noteBookId
  821. ];
  822. }
  823. /**
  824. * @param array $values
  825. * @param int $forumId
  826. * @return array
  827. */
  828. public function saveForumThread(array $values, $forumId)
  829. {
  830. require_once api_get_path(SYS_CODE_PATH) . 'forum/forumfunction.inc.php';
  831. $forum = get_forums($forumId, $this->course->getCode());
  832. $courseInfo = api_get_course_info($this->course->getCode());
  833. $sessionId = $this->session ? $this->session->getId() : 0;
  834. $id = store_thread($forum, $values, $courseInfo, false, $this->user->getId(), $sessionId);
  835. return [
  836. 'registered' => $id
  837. ];
  838. }
  839. }