Rest.php 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. use Chamilo\CoreBundle\Entity\Course;
  4. use Chamilo\CoreBundle\Entity\ExtraFieldValues;
  5. use Chamilo\CoreBundle\Entity\Session;
  6. use Chamilo\CourseBundle\Entity\CLpCategory;
  7. use Chamilo\CourseBundle\Entity\CNotebook;
  8. use Chamilo\CourseBundle\Entity\Repository\CNotebookRepository;
  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 SAVE_COURSE = 'save_course';
  41. const SAVE_USER = 'save_user';
  42. const SUBSCRIBE_USER_TO_COURSE = 'subscribe_user_to_course';
  43. const EXTRAFIELD_GCM_ID = 'gcm_registration_id';
  44. /**
  45. * @var Session
  46. */
  47. private $session;
  48. /**
  49. * @var Course
  50. */
  51. private $course;
  52. /**
  53. * Rest constructor.
  54. *
  55. * @param string $username
  56. * @param string $apiKey
  57. */
  58. public function __construct($username, $apiKey)
  59. {
  60. parent::__construct($username, $apiKey);
  61. }
  62. /**
  63. * Set the current course.
  64. *
  65. * @param int $id
  66. *
  67. * @throws Exception
  68. */
  69. public function setCourse($id)
  70. {
  71. if (!$id) {
  72. $this->course = null;
  73. return;
  74. }
  75. $em = Database::getManager();
  76. /** @var Course $course */
  77. $course = $em->find('ChamiloCoreBundle:Course', $id);
  78. if (!$course) {
  79. throw new Exception(get_lang('NoCourse'));
  80. }
  81. $this->course = $course;
  82. }
  83. /** Set the current session
  84. * @param int $id
  85. *
  86. * @throws Exception
  87. */
  88. public function setSession($id)
  89. {
  90. if (!$id) {
  91. $this->session = null;
  92. return;
  93. }
  94. $em = Database::getManager();
  95. /** @var Session $session */
  96. $session = $em->find('ChamiloCoreBundle:Session', $id);
  97. if (!$session) {
  98. throw new Exception(get_lang('NoSession'));
  99. }
  100. $this->session = $session;
  101. }
  102. /**
  103. * @param string $username
  104. * @param string $apiKeyToValidate
  105. *
  106. * @throws Exception
  107. *
  108. * @return Rest
  109. */
  110. public static function validate($username, $apiKeyToValidate)
  111. {
  112. $apiKey = self::findUserApiKey($username, self::SERVIVE_NAME);
  113. if ($apiKey != $apiKeyToValidate) {
  114. throw new Exception(get_lang('InvalidApiKey'));
  115. }
  116. return new self($username, $apiKey);
  117. }
  118. /**
  119. * Create the gcm_registration_id extra field for users.
  120. */
  121. public static function init()
  122. {
  123. $extraField = new ExtraField('user');
  124. $fieldInfo = $extraField->get_handler_field_info_by_field_variable(self::EXTRA_FIELD_GCM_REGISTRATION);
  125. if (empty($fieldInfo)) {
  126. $extraField->save([
  127. 'variable' => self::EXTRA_FIELD_GCM_REGISTRATION,
  128. 'field_type' => ExtraField::FIELD_TYPE_TEXT,
  129. 'display_text' => self::EXTRA_FIELD_GCM_REGISTRATION,
  130. ]);
  131. }
  132. }
  133. /**
  134. * @param string $registrationId
  135. *
  136. * @return bool
  137. */
  138. public function setGcmId($registrationId)
  139. {
  140. $registrationId = Security::remove_XSS($registrationId);
  141. $extraFieldValue = new ExtraFieldValue('user');
  142. return $extraFieldValue->save([
  143. 'variable' => self::EXTRA_FIELD_GCM_REGISTRATION,
  144. 'value' => $registrationId,
  145. 'item_id' => $this->user->getId(),
  146. ]);
  147. }
  148. /**
  149. * @param int $lastMessageId
  150. *
  151. * @return array
  152. */
  153. public function getUserMessages($lastMessageId = 0)
  154. {
  155. $lastMessages = MessageManager::getMessagesFromLastReceivedMessage($this->user->getId(), $lastMessageId);
  156. $messages = [];
  157. foreach ($lastMessages as $message) {
  158. $hasAttachments = MessageManager::hasAttachments($message['id']);
  159. $messages[] = [
  160. 'id' => $message['id'],
  161. 'title' => $message['title'],
  162. 'sender' => [
  163. 'id' => $message['user_id'],
  164. 'lastname' => $message['lastname'],
  165. 'firstname' => $message['firstname'],
  166. 'completeName' => api_get_person_name($message['firstname'], $message['lastname']),
  167. ],
  168. 'sendDate' => $message['send_date'],
  169. 'content' => $message['content'],
  170. 'hasAttachments' => $hasAttachments,
  171. 'url' => '',
  172. ];
  173. }
  174. return $messages;
  175. }
  176. /**
  177. * Get the user courses.
  178. *
  179. * @return array
  180. */
  181. public function getUserCourses()
  182. {
  183. $courses = CourseManager::get_courses_list_by_user_id($this->user->getId());
  184. $data = [];
  185. foreach ($courses as $courseId) {
  186. /** @var Course $course */
  187. $course = Database::getManager()->find('ChamiloCoreBundle:Course', $courseId['real_id']);
  188. $teachers = CourseManager::getTeacherListFromCourseCodeToString($course->getCode());
  189. $data[] = [
  190. 'id' => $course->getId(),
  191. 'title' => $course->getTitle(),
  192. 'code' => $course->getCode(),
  193. 'directory' => $course->getDirectory(),
  194. 'urlPicture' => CourseManager::getPicturePath($course, true),
  195. 'teachers' => $teachers,
  196. ];
  197. }
  198. return $data;
  199. }
  200. /**
  201. * @throws Exception
  202. *
  203. * @return array
  204. */
  205. public function getCourseInfo()
  206. {
  207. $teachers = CourseManager::getTeacherListFromCourseCodeToString($this->course->getCode());
  208. $tools = CourseHome::get_tools_category(
  209. TOOL_STUDENT_VIEW,
  210. $this->course->getId(),
  211. $this->session ? $this->session->getId() : 0
  212. );
  213. return [
  214. 'id' => $this->course->getId(),
  215. 'title' => $this->course->getTitle(),
  216. 'code' => $this->course->getCode(),
  217. 'directory' => $this->course->getDirectory(),
  218. 'urlPicture' => CourseManager::getPicturePath($this->course, true),
  219. 'teachers' => $teachers,
  220. 'tools' => array_map(
  221. function ($tool) {
  222. return ['type' => $tool['name']];
  223. },
  224. $tools
  225. ),
  226. ];
  227. }
  228. /**
  229. * Get the course descriptions.
  230. *
  231. * @throws Exception
  232. *
  233. * @return array
  234. */
  235. public function getCourseDescriptions()
  236. {
  237. $descriptions = CourseDescription::get_descriptions($this->course->getId());
  238. $results = [];
  239. /** @var CourseDescription $description */
  240. foreach ($descriptions as $description) {
  241. $results[] = [
  242. 'id' => $description->get_description_type(),
  243. 'title' => $description->get_title(),
  244. 'content' => str_replace('src="/', 'src="'.api_get_path(WEB_PATH), $description->get_content()),
  245. ];
  246. }
  247. return $results;
  248. }
  249. /**
  250. * @param int $directoryId
  251. *
  252. * @throws Exception
  253. *
  254. * @return array
  255. */
  256. public function getCourseDocuments($directoryId = 0)
  257. {
  258. /** @var string $path */
  259. $path = '/';
  260. $sessionId = $this->session ? $this->session->getId() : 0;
  261. if ($directoryId) {
  262. $directory = DocumentManager::get_document_data_by_id(
  263. $directoryId,
  264. $this->course->getCode(),
  265. false,
  266. $sessionId
  267. );
  268. if (!$directory) {
  269. throw new Exception('NoDataAvailable');
  270. }
  271. $path = $directory['path'];
  272. }
  273. $courseInfo = api_get_course_info_by_id($this->course->getId());
  274. $documents = DocumentManager::getAllDocumentData(
  275. $courseInfo,
  276. $path,
  277. 0,
  278. null,
  279. false,
  280. false,
  281. $sessionId
  282. );
  283. $results = [];
  284. if (!empty($documents)) {
  285. $webPath = api_get_path(WEB_CODE_PATH).'document/document.php?';
  286. /** @var array $document */
  287. foreach ($documents as $document) {
  288. if ($document['visibility'] != '1') {
  289. continue;
  290. }
  291. $icon = $document['filetype'] == 'file'
  292. ? choose_image($document['path'])
  293. : chooseFolderIcon($document['path']);
  294. $results[] = [
  295. 'id' => $document['id'],
  296. 'type' => $document['filetype'],
  297. 'title' => $document['title'],
  298. 'path' => $document['path'],
  299. 'url' => $webPath.http_build_query([
  300. 'username' => $this->user->getUsername(),
  301. 'api_key' => $this->apiKey,
  302. 'cidReq' => $this->course->getCode(),
  303. 'id_session' => $sessionId,
  304. 'gidReq' => 0,
  305. 'gradebook' => 0,
  306. 'origin' => '',
  307. 'action' => 'download',
  308. 'id' => $document['id'],
  309. ]),
  310. 'icon' => $icon,
  311. 'size' => format_file_size($document['size']),
  312. ];
  313. }
  314. }
  315. return $results;
  316. }
  317. /**
  318. * @throws Exception
  319. *
  320. * @return array
  321. */
  322. public function getCourseAnnouncements()
  323. {
  324. $sessionId = $this->session ? $this->session->getId() : 0;
  325. $announcements = AnnouncementManager::getAnnouncements(
  326. null,
  327. null,
  328. false,
  329. null,
  330. null,
  331. null,
  332. null,
  333. null,
  334. 0,
  335. $this->user->getId(),
  336. $this->course->getId(),
  337. $sessionId
  338. );
  339. $announcements = array_map(
  340. function ($announcement) {
  341. return [
  342. 'id' => intval($announcement['id']),
  343. 'title' => strip_tags($announcement['title']),
  344. 'creatorName' => strip_tags($announcement['username']),
  345. 'date' => strip_tags($announcement['insert_date']),
  346. ];
  347. },
  348. $announcements
  349. );
  350. return $announcements;
  351. }
  352. /**
  353. * @param int $announcementId
  354. *
  355. * @throws Exception
  356. *
  357. * @return array
  358. */
  359. public function getCourseAnnouncement($announcementId)
  360. {
  361. $sessionId = $this->session ? $this->session->getId() : 0;
  362. $announcement = AnnouncementManager::getAnnouncementInfoById(
  363. $announcementId,
  364. $this->course->getId(),
  365. $this->user->getId()
  366. );
  367. if (!$announcement) {
  368. throw new Exception(get_lang('NoAnnouncement'));
  369. }
  370. return [
  371. 'id' => intval($announcement['announcement']->getIid()),
  372. 'title' => $announcement['announcement']->getTitle(),
  373. 'creatorName' => $announcement['item_property']->getInsertUser()->getCompleteName(),
  374. 'date' => api_convert_and_format_date(
  375. $announcement['item_property']->getInsertDate(),
  376. DATE_TIME_FORMAT_LONG_24H
  377. ),
  378. 'content' => AnnouncementManager::parseContent(
  379. $this->user->getId(),
  380. $announcement['announcement']->getContent(),
  381. $this->course->getCode(),
  382. $sessionId
  383. ),
  384. ];
  385. }
  386. /**
  387. * @throws Exception
  388. *
  389. * @return array
  390. */
  391. public function getCourseAgenda()
  392. {
  393. $sessionId = $this->session ? $this->session->getId() : 0;
  394. $agenda = new Agenda(
  395. 'course',
  396. $this->user->getId(),
  397. $this->course->getId(),
  398. $sessionId
  399. );
  400. $result = $agenda->parseAgendaFilter(null);
  401. $start = new DateTime(api_get_utc_datetime(), new DateTimeZone('UTC'));
  402. $start->modify('first day of this month');
  403. $start->setTime(0, 0, 0);
  404. $end = new DateTime(api_get_utc_datetime(), new DateTimeZone('UTC'));
  405. $end->modify('last day of this month');
  406. $end->setTime(23, 59, 59);
  407. $groupId = current($result['groups']);
  408. $userId = current($result['users']);
  409. $events = $agenda->getEvents(
  410. $start->getTimestamp(),
  411. $end->getTimestamp(),
  412. $this->course->getId(),
  413. $groupId,
  414. $userId,
  415. 'array'
  416. );
  417. if (!is_array($events)) {
  418. return [];
  419. }
  420. $webPath = api_get_path(WEB_PATH);
  421. return array_map(
  422. function ($event) use ($webPath) {
  423. return [
  424. 'id' => intval($event['unique_id']),
  425. 'title' => $event['title'],
  426. 'content' => str_replace('src="/', 'src="'.$webPath, $event['description']),
  427. 'startDate' => $event['start_date_localtime'],
  428. 'endDate' => $event['end_date_localtime'],
  429. 'isAllDay' => $event['allDay'] ? true : false,
  430. ];
  431. },
  432. $events
  433. );
  434. }
  435. /**
  436. * @throws Exception
  437. *
  438. * @return array
  439. */
  440. public function getCourseNotebooks()
  441. {
  442. $em = Database::getManager();
  443. /** @var CNotebookRepository $notebooksRepo */
  444. $notebooksRepo = $em->getRepository('ChamiloCourseBundle:CNotebook');
  445. $notebooks = $notebooksRepo->findByUser($this->user, $this->course, $this->session);
  446. return array_map(
  447. function (CNotebook $notebook) {
  448. return [
  449. 'id' => $notebook->getIid(),
  450. 'title' => $notebook->getTitle(),
  451. 'description' => $notebook->getDescription(),
  452. 'creationDate' => api_format_date(
  453. $notebook->getCreationDate()->getTimestamp()
  454. ),
  455. 'updateDate' => api_format_date(
  456. $notebook->getUpdateDate()->getTimestamp()
  457. ),
  458. ];
  459. },
  460. $notebooks
  461. );
  462. }
  463. /**
  464. * @throws Exception
  465. *
  466. * @return array
  467. */
  468. public function getCourseForumCategories()
  469. {
  470. $sessionId = $this->session ? $this->session->getId() : 0;
  471. $webCoursePath = api_get_path(WEB_COURSE_PATH).$this->course->getDirectory().'/upload/forum/images/';
  472. require_once api_get_path(SYS_CODE_PATH).'forum/forumfunction.inc.php';
  473. $categoriesFullData = get_forum_categories('', $this->course->getId(), $sessionId);
  474. $categories = [];
  475. $includeGroupsForums = api_get_setting('display_groups_forum_in_general_tool') === 'true';
  476. $forumsFullData = get_forums('', $this->course->getCode(), $includeGroupsForums, $sessionId);
  477. $forums = [];
  478. foreach ($forumsFullData as $forumId => $forumInfo) {
  479. $forum = [
  480. 'id' => intval($forumInfo['iid']),
  481. 'catId' => intval($forumInfo['forum_category']),
  482. 'title' => $forumInfo['forum_title'],
  483. 'description' => $forumInfo['forum_comment'],
  484. 'image' => $forumInfo['forum_image'] ? ($webCoursePath.$forumInfo['forum_image']) : '',
  485. 'numberOfThreads' => isset($forumInfo['number_of_threads']) ? intval($forumInfo['number_of_threads']) : 0,
  486. 'lastPost' => null,
  487. ];
  488. $lastPostInfo = get_last_post_information($forumId, false, $this->course->getId(), $sessionId);
  489. if ($lastPostInfo) {
  490. $forum['lastPost'] = [
  491. 'date' => api_convert_and_format_date($lastPostInfo['last_post_date']),
  492. 'user' => api_get_person_name(
  493. $lastPostInfo['last_poster_firstname'],
  494. $lastPostInfo['last_poster_lastname']
  495. ),
  496. ];
  497. }
  498. $forums[] = $forum;
  499. }
  500. foreach ($categoriesFullData as $category) {
  501. $categoryForums = array_filter(
  502. $forums,
  503. function (array $forum) use ($category) {
  504. if ($forum['catId'] != $category['cat_id']) {
  505. return false;
  506. }
  507. return true;
  508. }
  509. );
  510. $categories[] = [
  511. 'id' => intval($category['iid']),
  512. 'title' => $category['cat_title'],
  513. 'catId' => intval($category['cat_id']),
  514. 'description' => $category['cat_comment'],
  515. 'forums' => $categoryForums,
  516. 'courseId' => $this->course->getId(),
  517. ];
  518. }
  519. return $categories;
  520. }
  521. /**
  522. * @param int $forumId
  523. *
  524. * @throws Exception
  525. *
  526. * @return array
  527. */
  528. public function getCourseForum($forumId)
  529. {
  530. require_once api_get_path(SYS_CODE_PATH).'forum/forumfunction.inc.php';
  531. $sessionId = $this->session ? $this->session->getId() : 0;
  532. $forumInfo = get_forums($forumId, $this->course->getCode(), true, $sessionId);
  533. if (!isset($forumInfo['iid'])) {
  534. throw new Exception(get_lang('NoForum'));
  535. }
  536. $webCoursePath = api_get_path(WEB_COURSE_PATH).$this->course->getDirectory().'/upload/forum/images/';
  537. $forum = [
  538. 'id' => $forumInfo['iid'],
  539. 'title' => $forumInfo['forum_title'],
  540. 'description' => $forumInfo['forum_comment'],
  541. 'image' => $forumInfo['forum_image'] ? ($webCoursePath.$forumInfo['forum_image']) : '',
  542. 'threads' => [],
  543. ];
  544. $threads = get_threads($forumInfo['iid'], $this->course->getId(), $sessionId);
  545. foreach ($threads as $thread) {
  546. $forum['threads'][] = [
  547. 'id' => $thread['iid'],
  548. 'title' => $thread['thread_title'],
  549. 'lastEditDate' => api_convert_and_format_date($thread['lastedit_date'], DATE_TIME_FORMAT_LONG_24H),
  550. 'numberOfReplies' => $thread['thread_replies'],
  551. 'numberOfViews' => $thread['thread_views'],
  552. 'author' => api_get_person_name($thread['firstname'], $thread['lastname']),
  553. ];
  554. }
  555. return $forum;
  556. }
  557. /**
  558. * @param int $forumId
  559. * @param int $threadId
  560. *
  561. * @return array
  562. */
  563. public function getCourseForumThread($forumId, $threadId)
  564. {
  565. require_once api_get_path(SYS_CODE_PATH).'forum/forumfunction.inc.php';
  566. $sessionId = $this->session ? $this->session->getId() : 0;
  567. $threadInfo = get_thread_information($forumId, $threadId, $sessionId);
  568. $thread = [
  569. 'id' => intval($threadInfo['iid']),
  570. 'cId' => intval($threadInfo['c_id']),
  571. 'title' => $threadInfo['thread_title'],
  572. 'forumId' => intval($threadInfo['forum_id']),
  573. 'posts' => [],
  574. ];
  575. $forumInfo = get_forums($threadInfo['forum_id'], $this->course->getCode(), true, $sessionId);
  576. $postsInfo = getPosts($forumInfo, $threadInfo['iid'], 'ASC');
  577. foreach ($postsInfo as $postInfo) {
  578. $thread['posts'][] = [
  579. 'id' => $postInfo['iid'],
  580. 'title' => $postInfo['post_title'],
  581. 'text' => $postInfo['post_text'],
  582. 'author' => api_get_person_name($postInfo['firstname'], $postInfo['lastname']),
  583. 'date' => api_convert_and_format_date($postInfo['post_date'], DATE_TIME_FORMAT_LONG_24H),
  584. 'parentId' => $postInfo['post_parent_id'],
  585. ];
  586. }
  587. return $thread;
  588. }
  589. /**
  590. * @return array
  591. */
  592. public function getUserProfile()
  593. {
  594. $pictureInfo = UserManager::get_user_picture_path_by_id($this->user->getId(), 'web');
  595. $result = [
  596. 'pictureUri' => $pictureInfo['dir'].$pictureInfo['file'],
  597. 'fullName' => $this->user->getCompleteName(),
  598. 'username' => $this->user->getUsername(),
  599. 'officialCode' => $this->user->getOfficialCode(),
  600. 'phone' => $this->user->getPhone(),
  601. 'extra' => [],
  602. ];
  603. $fieldValue = new ExtraFieldValue('user');
  604. $extraInfo = $fieldValue->getAllValuesForAnItem($this->user->getId(), true);
  605. foreach ($extraInfo as $extra) {
  606. /** @var ExtraFieldValues $extraValue */
  607. $extraValue = $extra['value'];
  608. $result['extra'][] = [
  609. 'title' => $extraValue->getField()->getDisplayText(true),
  610. 'value' => $extraValue->getValue(),
  611. ];
  612. }
  613. return $result;
  614. }
  615. /**
  616. * @throws Exception
  617. *
  618. * @return array
  619. */
  620. public function getCourseLearnPaths()
  621. {
  622. $sessionId = $this->session ? $this->session->getId() : 0;
  623. $categoriesTempList = learnpath::getCategories($this->course->getId());
  624. $categoryNone = new CLpCategory();
  625. $categoryNone->setId(0);
  626. $categoryNone->setName(get_lang('WithOutCategory'));
  627. $categoryNone->setPosition(0);
  628. $categories = array_merge([$categoryNone], $categoriesTempList);
  629. $categoryData = [];
  630. /** @var CLpCategory $category */
  631. foreach ($categories as $category) {
  632. $learnPathList = new LearnpathList(
  633. $this->user->getId(),
  634. $this->course->getCode(),
  635. $sessionId,
  636. null,
  637. false,
  638. $category->getId()
  639. );
  640. $flatLpList = $learnPathList->get_flat_list();
  641. if (empty($flatLpList)) {
  642. continue;
  643. }
  644. $listData = [];
  645. foreach ($flatLpList as $lpId => $lpDetails) {
  646. if ($lpDetails['lp_visibility'] == 0) {
  647. continue;
  648. }
  649. if (!learnpath::is_lp_visible_for_student(
  650. $lpId,
  651. $this->user->getId(),
  652. $this->course->getCode(),
  653. $sessionId
  654. )) {
  655. continue;
  656. }
  657. $timeLimits = false;
  658. // This is an old LP (from a migration 1.8.7) so we do nothing
  659. if (empty($lpDetails['created_on']) && empty($lpDetails['modified_on'])) {
  660. $timeLimits = false;
  661. }
  662. // Checking if expired_on is ON
  663. if (!empty($lpDetails['expired_on'])) {
  664. $timeLimits = true;
  665. }
  666. if ($timeLimits) {
  667. if (!empty($lpDetails['publicated_on']) && !empty($lpDetails['expired_on'])) {
  668. $startTime = api_strtotime($lpDetails['publicated_on'], 'UTC');
  669. $endTime = api_strtotime($lpDetails['expired_on'], 'UTC');
  670. $now = time();
  671. $isActivedTime = false;
  672. if ($now > $startTime && $endTime > $now) {
  673. $isActivedTime = true;
  674. }
  675. if (!$isActivedTime) {
  676. continue;
  677. }
  678. }
  679. }
  680. $progress = learnpath::getProgress($lpId, $this->user->getId(), $this->course->getId(), $sessionId);
  681. $listData[] = [
  682. 'id' => $lpId,
  683. 'title' => Security::remove_XSS($lpDetails['lp_name']),
  684. 'progress' => intval($progress),
  685. 'url' => api_get_path(WEB_CODE_PATH).'webservices/api/v2.php?'.http_build_query([
  686. 'hash' => $this->encodeParams([
  687. 'action' => 'course_learnpath',
  688. 'lp_id' => $lpId,
  689. 'course' => $this->course->getId(),
  690. 'session' => $sessionId,
  691. ]),
  692. ]),
  693. ];
  694. }
  695. if (empty($listData)) {
  696. continue;
  697. }
  698. $categoryData[] = [
  699. 'id' => $category->getId(),
  700. 'name' => $category->getName(),
  701. 'learnpaths' => $listData,
  702. ];
  703. }
  704. return $categoryData;
  705. }
  706. /**
  707. * @param string $encoded
  708. *
  709. * @return array
  710. */
  711. public static function decodeParams($encoded)
  712. {
  713. $decoded = json_decode($encoded);
  714. return $decoded;
  715. }
  716. /**
  717. * Start login for a user. Then make a redirect to show the learnpath.
  718. *
  719. * @param int $lpId
  720. */
  721. public function showLearningPath($lpId)
  722. {
  723. $loggedUser['user_id'] = $this->user->getId();
  724. $loggedUser['status'] = $this->user->getStatus();
  725. $loggedUser['uidReset'] = true;
  726. $sessionId = $this->session ? $this->session->getId() : 0;
  727. ChamiloSession::write('_user', $loggedUser);
  728. Login::init_user($this->user->getId(), true);
  729. $url = api_get_path(WEB_CODE_PATH).'lp/lp_controller.php?'.http_build_query([
  730. 'cidReq' => $this->course->getCode(),
  731. 'id_session' => $sessionId,
  732. 'gidReq' => 0,
  733. 'gradebook' => 0,
  734. 'origin' => '',
  735. 'action' => 'view',
  736. 'lp_id' => intval($lpId),
  737. 'isStudentView' => 'true',
  738. ]);
  739. header("Location: $url");
  740. exit;
  741. }
  742. /**
  743. * @param array $postValues
  744. * @param int $forumId
  745. *
  746. * @return array
  747. */
  748. public function saveForumPost(array $postValues, $forumId)
  749. {
  750. require_once api_get_path(SYS_CODE_PATH).'forum/forumfunction.inc.php';
  751. $forum = get_forums($forumId, $this->course->getCode());
  752. store_reply($forum, $postValues, $this->course->getId(), $this->user->getId());
  753. return [
  754. 'registered' => true,
  755. ];
  756. }
  757. /**
  758. * Get the list of sessions for current user.
  759. *
  760. * @return array the sessions list
  761. */
  762. public function getUserSessions()
  763. {
  764. $data = [];
  765. $sessionsByCategory = UserManager::get_sessions_by_category($this->user->getId(), false);
  766. foreach ($sessionsByCategory as $category) {
  767. $categorySessions = [];
  768. foreach ($category['sessions'] as $sessions) {
  769. $sessionCourses = [];
  770. foreach ($sessions['courses'] as $course) {
  771. $courseInfo = api_get_course_info_by_id($course['real_id']);
  772. $teachers = SessionManager::getCoachesByCourseSessionToString(
  773. $sessions['session_id'],
  774. $course['real_id']
  775. );
  776. $sessionCourses[] = [
  777. 'id' => $courseInfo['real_id'],
  778. 'title' => $courseInfo['title'],
  779. 'code' => $courseInfo['code'],
  780. 'directory' => $courseInfo['directory'],
  781. 'pictureUrl' => $courseInfo['course_image_large'],
  782. 'teachers' => $teachers,
  783. ];
  784. }
  785. $sessionBox = Display::getSessionTitleBox($sessions['session_id']);
  786. $categorySessions[] = [
  787. 'name' => $sessionBox['title'],
  788. 'id' => $sessions['session_id'],
  789. 'date' => $sessionBox['dates'],
  790. 'duration' => isset($sessionBox['duration']) ? $sessionBox['duration'] : null,
  791. 'courses' => $sessionCourses,
  792. ];
  793. }
  794. $data[] = [
  795. 'id' => $category['session_category']['id'],
  796. 'name' => $category['session_category']['name'],
  797. 'sessions' => $categorySessions,
  798. ];
  799. }
  800. return $data;
  801. }
  802. /**
  803. * @param string $subject
  804. * @param string $text
  805. * @param array $receivers
  806. *
  807. * @return array
  808. */
  809. public function saveUserMessage($subject, $text, array $receivers)
  810. {
  811. foreach ($receivers as $userId) {
  812. MessageManager::send_message($userId, $subject, $text);
  813. }
  814. return [
  815. 'sent' => true,
  816. ];
  817. }
  818. /**
  819. * @param string $search
  820. *
  821. * @return array
  822. */
  823. public function getMessageUsers($search)
  824. {
  825. $repo = UserManager::getRepository();
  826. $users = $repo->findUsersToSendMessage($this->user->getId(), $search);
  827. $showEmail = api_get_setting('show_email_addresses') === 'true';
  828. $data = [];
  829. /** @var User $user */
  830. foreach ($users as $user) {
  831. $userName = $user->getCompleteName();
  832. if ($showEmail) {
  833. $userName .= " ({$user->getEmail()})";
  834. }
  835. $data[] = [
  836. 'id' => $user->getId(),
  837. 'name' => $userName,
  838. ];
  839. }
  840. return $data;
  841. }
  842. /**
  843. * @param string $title
  844. * @param string $text
  845. *
  846. * @return array
  847. */
  848. public function saveCourseNotebook($title, $text)
  849. {
  850. $values = ['note_title' => $title, 'note_comment' => $text];
  851. $sessionId = $this->session ? $this->session->getId() : 0;
  852. $noteBookId = NotebookManager::save_note(
  853. $values,
  854. $this->user->getId(),
  855. $this->course->getId(),
  856. $sessionId
  857. );
  858. return [
  859. 'registered' => $noteBookId,
  860. ];
  861. }
  862. /**
  863. * @param array $values
  864. * @param int $forumId
  865. *
  866. * @return array
  867. */
  868. public function saveForumThread(array $values, $forumId)
  869. {
  870. require_once api_get_path(SYS_CODE_PATH).'forum/forumfunction.inc.php';
  871. $sessionId = $this->session ? $this->session->getId() : 0;
  872. $forum = get_forums($forumId, $this->course->getCode(), true, $sessionId);
  873. $courseInfo = api_get_course_info($this->course->getCode());
  874. $thread = store_thread($forum, $values, $courseInfo, false, $this->user->getId(), $sessionId);
  875. return [
  876. 'registered' => $thread->getIid(),
  877. ];
  878. }
  879. /**
  880. * @param array $courseParam
  881. *
  882. * @return array
  883. */
  884. public function addCourse(array $courseParam)
  885. {
  886. $tableCourse = Database::get_main_table(TABLE_MAIN_COURSE);
  887. $extraList = [];
  888. $results = [];
  889. $title = isset($courseParam['title']) ? $courseParam['title'] : '';
  890. $categoryCode = isset($courseParam['category_code']) ? $courseParam['category_code'] : '';
  891. $wantedCode = isset($courseParam['wanted_code']) ? intval($courseParam['wanted_code']) : 0;
  892. $tutorName = isset($courseParam['tutor_name']) ? $courseParam['tutor_name'] : '';
  893. $courseLanguage = isset($courseParam['language']) ? $courseParam['language'] : null;
  894. $originalCourseIdName = isset($courseParam['original_course_id_name'])
  895. ? $courseParam['original_course_id_name']
  896. : null;
  897. $originalCourseIdValue = isset($courseParam['original_course_id_value'])
  898. ? $courseParam['original_course_id_value']
  899. : null;
  900. $diskQuota = isset($courseParam['disk_quota']) ? $courseParam['disk_quota'] : '100';
  901. $visibility = isset($courseParam['visibility']) ? (int) $courseParam['visibility'] : null;
  902. if (isset($courseParam['visibility'])) {
  903. if ($courseParam['visibility'] &&
  904. $courseParam['visibility'] >= 0 &&
  905. $courseParam['visibility'] <= 3
  906. ) {
  907. $visibility = (int) $courseParam['visibility'];
  908. }
  909. }
  910. // Check whether exits $x_course_code into user_field_values table.
  911. $courseInfo = CourseManager::getCourseInfoFromOriginalId(
  912. $originalCourseIdValue,
  913. $originalCourseIdName
  914. );
  915. if (!empty($courseInfo)) {
  916. if ($courseInfo['visibility'] != 0) {
  917. $sql = "UPDATE $tableCourse SET
  918. course_language = '".Database::escape_string($courseLanguage)."',
  919. title = '".Database::escape_string($title)."',
  920. category_code = '".Database::escape_string($categoryCode)."',
  921. tutor_name = '".Database::escape_string($tutorName)."',
  922. visual_code = '".Database::escape_string($wantedCode)."'";
  923. if ($visibility !== null) {
  924. $sql .= ", visibility = $visibility ";
  925. }
  926. $sql .= " WHERE id = ".$courseInfo['real_id'];
  927. Database::query($sql);
  928. if (is_array($extraList) && count($extraList) > 0) {
  929. foreach ($extraList as $extra) {
  930. $extraFieldName = $extra['field_name'];
  931. $extraFieldValue = $extra['field_value'];
  932. // Save the external system's id into course_field_value table.
  933. CourseManager::update_course_extra_field_value(
  934. $courseInfo['code'],
  935. $extraFieldName,
  936. $extraFieldValue
  937. );
  938. }
  939. }
  940. $results[] = $courseInfo['code'];
  941. }
  942. }
  943. $params = [];
  944. $params['title'] = $title;
  945. $params['wanted_code'] = $wantedCode;
  946. $params['category_code'] = $categoryCode;
  947. $params['course_category'] = $categoryCode;
  948. $params['tutor_name'] = $tutorName;
  949. $params['course_language'] = $courseLanguage;
  950. $params['user_id'] = $this->user->getId();
  951. $params['visibility'] = $visibility;
  952. $params['disk_quota'] = $diskQuota;
  953. $params['subscribe'] = empty($courseParam['subscribe']) ? 0 : 1;
  954. $params['unsubscribe'] = empty($courseParam['unsubscribe']) ? 0 : 1;
  955. $courseInfo = CourseManager::create_course($params, $params['user_id']);
  956. if (!empty($courseInfo)) {
  957. $courseCode = $courseInfo['code'];
  958. // Save new field label into course_field table
  959. CourseManager::create_course_extra_field(
  960. $originalCourseIdName,
  961. 1,
  962. $originalCourseIdName,
  963. ''
  964. );
  965. // Save the external system's id into user_field_value table.
  966. CourseManager::update_course_extra_field_value(
  967. $courseCode,
  968. $originalCourseIdName,
  969. $originalCourseIdValue
  970. );
  971. if (is_array($extraList) && count($extraList) > 0) {
  972. foreach ($extraList as $extra) {
  973. $extraFieldName = $extra['field_name'];
  974. $extraFieldValue = $extra['field_value'];
  975. // Save new fieldlabel into course_field table.
  976. CourseManager::create_course_extra_field(
  977. $extraFieldName,
  978. 1,
  979. $extraFieldName,
  980. ''
  981. );
  982. // Save the external system's id into course_field_value table.
  983. CourseManager::update_course_extra_field_value(
  984. $courseCode,
  985. $extraFieldName,
  986. $extraFieldValue
  987. );
  988. }
  989. }
  990. $results[] = $courseCode;
  991. }
  992. return $results;
  993. }
  994. /**
  995. * @param $user_param
  996. *
  997. * @return array
  998. */
  999. public function addUser($user_param)
  1000. {
  1001. $results = [];
  1002. $orig_user_id_value = [];
  1003. $userManager = UserManager::getManager();
  1004. $firstName = $user_param['firstname'];
  1005. $lastName = $user_param['lastname'];
  1006. $status = $user_param['status'];
  1007. $email = $user_param['email'];
  1008. $loginName = $user_param['loginname'];
  1009. $password = $user_param['password'];
  1010. $official_code = '';
  1011. $language = '';
  1012. $phone = '';
  1013. $picture_uri = '';
  1014. $auth_source = PLATFORM_AUTH_SOURCE;
  1015. $expiration_date = '';
  1016. $active = 1;
  1017. $hr_dept_id = 0;
  1018. $extra = null;
  1019. $original_user_id_name = $user_param['original_user_id_name'];
  1020. $original_user_id_value = $user_param['original_user_id_value'];
  1021. $orig_user_id_value[] = $user_param['original_user_id_value'];
  1022. $extra_list = $user_param['extra'];
  1023. if (!empty($user_param['language'])) {
  1024. $language = $user_param['language'];
  1025. }
  1026. if (!empty($user_param['phone'])) {
  1027. $phone = $user_param['phone'];
  1028. }
  1029. if (!empty($user_param['expiration_date'])) {
  1030. $expiration_date = $user_param['expiration_date'];
  1031. }
  1032. // Default language.
  1033. if (empty($language)) {
  1034. $language = api_get_setting('platformLanguage');
  1035. }
  1036. // First check wether the login already exists.
  1037. if (!UserManager::is_username_available($loginName)) {
  1038. $results[] = 0;
  1039. }
  1040. $userId = UserManager::create_user(
  1041. $firstName,
  1042. $lastName,
  1043. $status,
  1044. $email,
  1045. $loginName,
  1046. $password,
  1047. $official_code,
  1048. $language,
  1049. $phone,
  1050. $picture_uri,
  1051. $auth_source,
  1052. $expiration_date,
  1053. $active,
  1054. $hr_dept_id
  1055. );
  1056. if ($userId) {
  1057. if (api_is_multiple_url_enabled()) {
  1058. if (api_get_current_access_url_id() != -1) {
  1059. UrlManager::add_user_to_url(
  1060. $userId,
  1061. api_get_current_access_url_id()
  1062. );
  1063. } else {
  1064. UrlManager::add_user_to_url($userId, 1);
  1065. }
  1066. } else {
  1067. // We add by default the access_url_user table with access_url_id = 1
  1068. UrlManager::add_user_to_url($userId, 1);
  1069. }
  1070. // Save new field label into user_field table.
  1071. UserManager::create_extra_field(
  1072. $original_user_id_name,
  1073. 1,
  1074. $original_user_id_name,
  1075. ''
  1076. );
  1077. // Save the external system's id into user_field_value table.
  1078. UserManager::update_extra_field_value(
  1079. $userId,
  1080. $original_user_id_name,
  1081. $original_user_id_value
  1082. );
  1083. if (is_array($extra_list) && count($extra_list) > 0) {
  1084. foreach ($extra_list as $extra) {
  1085. $extra_field_name = $extra['field_name'];
  1086. $extra_field_value = $extra['field_value'];
  1087. // Save new field label into user_field table.
  1088. UserManager::create_extra_field(
  1089. $extra_field_name,
  1090. 1,
  1091. $extra_field_name,
  1092. ''
  1093. );
  1094. // Save the external system's id into user_field_value table.
  1095. UserManager::update_extra_field_value(
  1096. $userId,
  1097. $extra_field_name,
  1098. $extra_field_value
  1099. );
  1100. }
  1101. }
  1102. $results[] = $userId;
  1103. } else {
  1104. $results[] = 0;
  1105. }
  1106. return $results;
  1107. }
  1108. /**
  1109. * Subscribe User to Course.
  1110. *
  1111. * @param array $params
  1112. *
  1113. * @return array
  1114. */
  1115. public function subscribeUserToCourse($params)
  1116. {
  1117. $course_id = $params['course_id'];
  1118. $course_code = $params['course_code'];
  1119. $user_id = $params['user_id'];
  1120. if (!$course_id && !$course_code) {
  1121. return [false];
  1122. }
  1123. if (!$course_code) {
  1124. $course_code = CourseManager::get_course_code_from_course_id($course_id);
  1125. }
  1126. if (CourseManager::subscribeUser($user_id, $course_code)) {
  1127. return [true];
  1128. } else {
  1129. return [false];
  1130. }
  1131. return [true];
  1132. }
  1133. /**
  1134. * @param array $additionalParams Optional
  1135. *
  1136. * @return string
  1137. */
  1138. private function encodeParams(array $additionalParams = [])
  1139. {
  1140. $params = array_merge($additionalParams, [
  1141. 'api_key' => $this->apiKey,
  1142. 'username' => $this->user->getUsername(),
  1143. ]);
  1144. $encoded = json_encode($params);
  1145. return $encoded;
  1146. }
  1147. }