LearningCalendarPlugin.php 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161
  1. <?php
  2. /* For license terms, see /license.txt */
  3. /**
  4. * Class LearningCalendarPlugin.
  5. */
  6. class LearningCalendarPlugin extends Plugin
  7. {
  8. const EVENT_TYPE_TAKEN = 1;
  9. const EVENT_TYPE_EXAM = 2;
  10. const EVENT_TYPE_FREE = 3;
  11. /**
  12. * Class constructor.
  13. */
  14. protected function __construct()
  15. {
  16. $version = '0.1';
  17. $author = 'Julio Montoya';
  18. parent::__construct($version, $author, ['enabled' => 'boolean']);
  19. $this->setHasPersonalEvents(true);
  20. }
  21. /**
  22. * Event definition.
  23. *
  24. * @return array
  25. */
  26. public function getEventTypeList()
  27. {
  28. return [
  29. self::EVENT_TYPE_TAKEN => ['color' => 'red', 'name' => self::get_lang('EventTypeTaken')],
  30. self::EVENT_TYPE_EXAM => ['color' => 'yellow', 'name' => self::get_lang('EventTypeExam')],
  31. self::EVENT_TYPE_FREE => ['color' => 'green', 'name' => self::get_lang('EventTypeFree')],
  32. ];
  33. }
  34. /**
  35. * @return array
  36. */
  37. public function getEventTypeColorList()
  38. {
  39. $list = $this->getEventTypeList();
  40. $newList = [];
  41. foreach ($list as $eventId => $event) {
  42. $newList[$eventId] = $event['color'];
  43. }
  44. return $newList;
  45. }
  46. /**
  47. * Get the class instance.
  48. *
  49. * @return $this
  50. */
  51. public static function create()
  52. {
  53. static $result = null;
  54. return $result ?: $result = new self();
  55. }
  56. /**
  57. * Get the plugin directory name.
  58. */
  59. public function get_name()
  60. {
  61. return 'learning_calendar';
  62. }
  63. /**
  64. * Install the plugin. Setup the database.
  65. */
  66. public function install()
  67. {
  68. $sql = "
  69. CREATE TABLE IF NOT EXISTS learning_calendar(
  70. id int not null AUTO_INCREMENT primary key,
  71. title varchar(255) not null default '',
  72. description longtext default null,
  73. total_hours int not null default 0,
  74. minutes_per_day int not null default 0,
  75. disabled int default 0,
  76. author_id int(11) not null
  77. )
  78. ";
  79. Database::query($sql);
  80. $sql = "
  81. CREATE TABLE IF NOT EXISTS learning_calendar_events(
  82. id int not null AUTO_INCREMENT primary key,
  83. name varchar(255) default '',
  84. calendar_id int not null,
  85. start_date date not null,
  86. end_date date not null,
  87. type int not null
  88. )
  89. ";
  90. Database::query($sql);
  91. $sql = "
  92. CREATE TABLE IF NOT EXISTS learning_calendar_user(
  93. id int not null AUTO_INCREMENT primary key,
  94. user_id int(11) not null,
  95. calendar_id int not null
  96. )
  97. ";
  98. Database::query($sql);
  99. $sql = "
  100. CREATE TABLE IF NOT EXISTS learning_calendar_control_point(
  101. id int not null AUTO_INCREMENT primary key,
  102. user_id int(11) not null,
  103. control_date date not null,
  104. control_value int not null,
  105. created_at datetime not null,
  106. updated_at datetime not null
  107. )
  108. ";
  109. Database::query($sql);
  110. $extraField = new ExtraField('lp_item');
  111. $params = [
  112. 'display_text' => $this->get_lang('Learning calendarOneDayMarker'),
  113. 'variable' => 'calendar',
  114. 'visible_to_self' => 1,
  115. 'changeable' => 1,
  116. 'visible_to_others' => 1,
  117. 'field_type' => ExtraField::FIELD_TYPE_CHECKBOX,
  118. ];
  119. $extraField->save($params);
  120. $extraField = new ExtraField('course');
  121. $params = [
  122. 'display_text' => $this->get_lang('Course duration (h)'),
  123. 'variable' => 'course_hours_duration',
  124. 'visible_to_self' => 1,
  125. 'changeable' => 1,
  126. 'visible_to_others' => 1,
  127. 'field_type' => ExtraField::FIELD_TYPE_TEXT,
  128. ];
  129. $extraField->save($params);
  130. return true;
  131. }
  132. /**
  133. * Uninstall the plugin.
  134. */
  135. public function uninstall()
  136. {
  137. $tables = [
  138. 'learning_calendar',
  139. 'learning_calendar_events',
  140. 'learning_calendar_user',
  141. ];
  142. foreach ($tables as $table) {
  143. $sql = "DROP TABLE IF EXISTS $table";
  144. Database::query($sql);
  145. }
  146. $extraField = new ExtraField('lp_item');
  147. $fieldInfo = $extraField->get_handler_field_info_by_field_variable('calendar');
  148. if ($fieldInfo) {
  149. $extraField->delete($fieldInfo['id']);
  150. }
  151. $extraField = new ExtraField('course');
  152. $fieldInfo = $extraField->get_handler_field_info_by_field_variable('course_hours_duration');
  153. if ($fieldInfo) {
  154. $extraField->delete($fieldInfo['id']);
  155. }
  156. return true;
  157. }
  158. /**
  159. * @param int $from
  160. * @param int $numberOfItems
  161. * @param int $column
  162. * @param string $direction
  163. *
  164. * @return array
  165. */
  166. public function getCalendars(
  167. $from,
  168. $numberOfItems,
  169. $column,
  170. $direction = 'DESC'
  171. ) {
  172. $column = (int) $column;
  173. $from = (int) $from;
  174. $numberOfItems = (int) $numberOfItems;
  175. $direction = strtoupper($direction);
  176. if (!in_array($direction, ['ASC', 'DESC'])) {
  177. $direction = 'DESC';
  178. }
  179. if (api_is_platform_admin()) {
  180. $sql = 'SELECT * FROM learning_calendar';
  181. } else {
  182. $userId = api_get_user_id();
  183. $sql = "SELECT * FROM learning_calendar WHERE author_id = $userId";
  184. }
  185. $sql .= " LIMIT $from, $numberOfItems ";
  186. $result = Database::query($sql);
  187. $list = [];
  188. $link = api_get_path(WEB_PLUGIN_PATH).'learning_calendar/start.php';
  189. while ($row = Database::fetch_array($result)) {
  190. $id = $row['id'];
  191. $row['title'] = Display::url(
  192. $row['title'],
  193. api_get_path(WEB_PLUGIN_PATH).'learning_calendar/calendar.php?id='.$id
  194. );
  195. $actions = Display::url(
  196. Display::return_icon('edit.png', get_lang('Edit')),
  197. $link.'?action=edit&id='.$id
  198. );
  199. $actions .= Display::url(
  200. Display::return_icon('copy.png', get_lang('Copy')),
  201. $link.'?action=copy&id='.$id
  202. );
  203. $actions .= Display::url(
  204. Display::return_icon('delete.png', get_lang('Delete')),
  205. $link.'?action=delete&id='.$id
  206. );
  207. $row['actions'] = $actions;
  208. $list[] = $row;
  209. }
  210. return $list;
  211. }
  212. /**
  213. * @param array $calendarInfo
  214. * @param int $start
  215. * @param int $end
  216. * @param int $type
  217. * @param bool $getCount
  218. *
  219. * @return array
  220. */
  221. public function getCalendarsEventsByDate($calendarInfo, $start, $end, $type = 0, $getCount = false)
  222. {
  223. if (empty($calendarInfo)) {
  224. if ($getCount) {
  225. return 0;
  226. }
  227. return [];
  228. }
  229. $calendarId = (int) $calendarInfo['id'];
  230. $start = (int) $start;
  231. $end = (int) $end;
  232. $startCondition = '';
  233. $endCondition = '';
  234. $typeCondition = '';
  235. if ($start !== 0) {
  236. $start = api_get_utc_datetime($start);
  237. $startCondition = "AND start_date >= '".$start."'";
  238. }
  239. if ($end !== 0) {
  240. $end = api_get_utc_datetime($end);
  241. $endCondition = "AND (end_date <= '".$end."' OR end_date IS NULL)";
  242. }
  243. if (!empty($type)) {
  244. $type = (int) $type;
  245. $typeCondition = " AND type = $type ";
  246. }
  247. $select = '*';
  248. if ($getCount) {
  249. $select = 'count(id) count ';
  250. }
  251. $sql = "SELECT $select FROM learning_calendar_events
  252. WHERE calendar_id = $calendarId $startCondition $endCondition $typeCondition";
  253. $result = Database::query($sql);
  254. if ($getCount) {
  255. $row = Database::fetch_array($result, 'ASSOC');
  256. return $row['count'];
  257. }
  258. $list = [];
  259. while ($row = Database::fetch_array($result, 'ASSOC')) {
  260. $list[] = $row;
  261. }
  262. return ['calendar' => $calendarInfo, 'events' => $list];
  263. }
  264. /**
  265. * @param array $calendarInfo
  266. *
  267. * @return array
  268. */
  269. public function getFirstCalendarDate($calendarInfo)
  270. {
  271. if (empty($calendarInfo)) {
  272. return [];
  273. }
  274. $calendarId = (int) $calendarInfo['id'];
  275. /*if (!empty($type)) {
  276. $type = (int) $type;
  277. $typeCondition = " AND type = $type ";
  278. }*/
  279. $sql = "SELECT start_date FROM learning_calendar_events
  280. WHERE calendar_id = $calendarId ORDER BY start_date LIMIT 1";
  281. $result = Database::query($sql);
  282. $row = Database::fetch_array($result, 'ASSOC');
  283. return $row['start_date'];
  284. }
  285. /**
  286. * @return int
  287. */
  288. public function getCalendarCount()
  289. {
  290. if (api_is_platform_admin()) {
  291. $sql = 'select count(*) as count FROM learning_calendar';
  292. } else {
  293. $userId = api_get_user_id();
  294. $sql = "select count(*) as count FROM learning_calendar WHERE author_id = $userId";
  295. }
  296. $result = Database::query($sql);
  297. $result = Database::fetch_array($result);
  298. return (int) $result['count'];
  299. }
  300. /**
  301. * @param int $calendarId
  302. *
  303. * @return array
  304. */
  305. public function getUsersPerCalendar($calendarId)
  306. {
  307. $calendarId = (int) $calendarId;
  308. $sql = "SELECT * FROM learning_calendar_user
  309. WHERE calendar_id = $calendarId";
  310. $result = Database::query($sql);
  311. $list = [];
  312. while ($row = Database::fetch_array($result, 'ASSOC')) {
  313. $userInfo = api_get_user_info($row['user_id']);
  314. $userInfo['exam'] = 'exam';
  315. $list[] = $userInfo;
  316. }
  317. return $list;
  318. }
  319. /**
  320. * @param int $calendarId
  321. *
  322. * @return int
  323. */
  324. public function getUsersPerCalendarCount($calendarId)
  325. {
  326. $calendarId = (int) $calendarId;
  327. $sql = "SELECT count(id) as count FROM learning_calendar_user
  328. WHERE calendar_id = $calendarId";
  329. $result = Database::query($sql);
  330. $row = Database::fetch_array($result, 'ASSOC');
  331. return (int) $row['count'];
  332. }
  333. /**
  334. * @param int $id
  335. */
  336. public function toggleVisibility($id)
  337. {
  338. $extraField = new ExtraField('lp_item');
  339. $fieldInfo = $extraField->get_handler_field_info_by_field_variable('calendar');
  340. if ($fieldInfo) {
  341. $itemInfo = $this->getItemVisibility($id);
  342. if (empty($itemInfo)) {
  343. $extraField = new ExtraFieldValue('lp_item');
  344. $value = 1;
  345. $params = [
  346. 'field_id' => $fieldInfo['id'],
  347. 'value' => $value,
  348. 'item_id' => $id,
  349. ];
  350. $extraField->save($params);
  351. } else {
  352. $newValue = (int) $itemInfo['value'] === 1 ? 0 : 1;
  353. $extraField = new ExtraFieldValue('lp_item');
  354. $params = [
  355. 'id' => $itemInfo['id'],
  356. 'value' => $newValue,
  357. ];
  358. $extraField->update($params);
  359. }
  360. }
  361. }
  362. /**
  363. * @param int $id
  364. *
  365. * @return array
  366. */
  367. public function getItemVisibility($id)
  368. {
  369. $extraField = new ExtraFieldValue('lp_item');
  370. $values = $extraField->get_values_by_handler_and_field_variable($id, 'calendar');
  371. if (empty($values)) {
  372. return [];
  373. }
  374. return $values;
  375. }
  376. /**
  377. * @param int $calendarId
  378. *
  379. * @return array|mixed
  380. */
  381. public function getCalendar($calendarId)
  382. {
  383. $calendarId = (int) $calendarId;
  384. $sql = "SELECT * FROM learning_calendar WHERE id = $calendarId";
  385. $result = Database::query($sql);
  386. $item = Database::fetch_array($result, 'ASSOC');
  387. return $item;
  388. }
  389. /**
  390. * @param int $userId
  391. *
  392. * @return array|mixed
  393. */
  394. public function getUserCalendar($userId)
  395. {
  396. $userId = (int) $userId;
  397. $sql = "SELECT * FROM learning_calendar_user WHERE user_id = $userId";
  398. $result = Database::query($sql);
  399. $item = Database::fetch_array($result, 'ASSOC');
  400. return $item;
  401. }
  402. /**
  403. * @param int $userId
  404. * @param int $start
  405. * @param int $end
  406. * @param int $type
  407. * @param bool $getCount
  408. *
  409. * @return array|int
  410. */
  411. public function getUserEvents($userId, $start, $end, $type = 0, $getCount = false)
  412. {
  413. $calendarRelUser = $this->getUserCalendar($userId);
  414. if (!empty($calendarRelUser)) {
  415. $calendar = $this->getCalendar($calendarRelUser['calendar_id']);
  416. return $this->getCalendarsEventsByDate($calendar, $start, $end, $type, $getCount);
  417. }
  418. if ($getCount) {
  419. return 0;
  420. }
  421. return [];
  422. }
  423. /**
  424. * @param int $userId
  425. *
  426. * @return mixed|string
  427. */
  428. public function getUserCalendarToString($userId)
  429. {
  430. $calendar = $this->getUserCalendar($userId);
  431. if ($calendar) {
  432. $calendarInfo = $this->getCalendar($calendar['calendar_id']);
  433. return $calendarInfo['title'];
  434. }
  435. return '';
  436. }
  437. /**
  438. * @param int $calendarId
  439. * @param int $userId
  440. *
  441. * @return bool
  442. */
  443. public function addUserToCalendar($calendarId, $userId)
  444. {
  445. $calendar = $this->getUserCalendar($userId);
  446. if (empty($calendar)) {
  447. $params = [
  448. 'calendar_id' => $calendarId,
  449. 'user_id' => $userId,
  450. ];
  451. Database::insert('learning_calendar_user', $params);
  452. return true;
  453. }
  454. return false;
  455. }
  456. /**
  457. * @param int $calendarId
  458. * @param int $userId
  459. *
  460. * @return bool
  461. */
  462. public function updateUserToCalendar($calendarId, $userId)
  463. {
  464. $calendar = $this->getUserCalendar($userId);
  465. if (!empty($calendar)) {
  466. $params = [
  467. 'calendar_id' => $calendarId,
  468. 'user_id' => $userId,
  469. ];
  470. Database::update('learning_calendar_user', $params, ['id = ?' => $calendar['id']]);
  471. }
  472. return true;
  473. }
  474. /**
  475. * @param int $calendarId
  476. * @param int $userId
  477. *
  478. * @return bool
  479. */
  480. public function deleteAllCalendarFromUser($calendarId, $userId)
  481. {
  482. $calendarId = (int) $calendarId;
  483. $userId = (int) $userId;
  484. $sql = "DELETE FROM learning_calendar_user
  485. WHERE user_id = $userId AND calendar_id = $calendarId";
  486. Database::query($sql);
  487. return true;
  488. }
  489. /*public static function getUserCalendar($calendarId, $userId)
  490. {
  491. $params = [
  492. 'calendar_id' => $calendarId,
  493. 'user_id' => $calendarId,
  494. ];
  495. Database::insert('learning_calendar_user', $params);
  496. return true;
  497. }*/
  498. /**
  499. * @param FormValidator $form
  500. */
  501. public function getForm(FormValidator &$form)
  502. {
  503. $form->addText('title', get_lang('Title'));
  504. $form->addText('total_hours', get_lang('Total hours'));
  505. $form->addText('minutes_per_day', get_lang('Minutes per day'));
  506. $form->addHtmlEditor('description', get_lang('Description'), false);
  507. }
  508. /**
  509. * @param Agenda $agenda
  510. * @param int $start
  511. * @param int $end
  512. *
  513. * @return array
  514. */
  515. public function getPersonalEvents($agenda, $start, $end)
  516. {
  517. $userId = api_get_user_id();
  518. $events = $this->getUserEvents($userId, $start, $end);
  519. if (empty($events)) {
  520. return [];
  521. }
  522. $calendarInfo = $events['calendar'];
  523. $events = $events['events'];
  524. $list = [];
  525. $typeList = $this->getEventTypeColorList();
  526. foreach ($events as $row) {
  527. $event = [];
  528. $event['id'] = 'personal_'.$row['id'];
  529. $event['title'] = $calendarInfo['title'];
  530. $event['className'] = 'personal';
  531. $color = isset($typeList[$row['type']]) ? $typeList[$row['type']] : $typeList[self::EVENT_TYPE_FREE];
  532. $event['borderColor'] = $color;
  533. $event['backgroundColor'] = $color;
  534. $event['editable'] = false;
  535. $event['sent_to'] = get_lang('Me');
  536. $event['type'] = 'personal';
  537. if (!empty($row['start_date'])) {
  538. $event['start'] = $agenda->formatEventDate($row['start_date']);
  539. $event['start_date_localtime'] = api_get_local_time($row['start_date']);
  540. }
  541. if (!empty($row['end_date'])) {
  542. $event['end'] = $agenda->formatEventDate($row['end_date']);
  543. $event['end_date_localtime'] = api_get_local_time($row['end_date']);
  544. }
  545. $event['description'] = 'plugin';
  546. $event['allDay'] = 1;
  547. $event['parent_event_id'] = 0;
  548. $event['has_children'] = 0;
  549. $list[] = $event;
  550. }
  551. return $list;
  552. }
  553. /**
  554. * @param int $userId
  555. * @param array $coursesAndSessions
  556. *
  557. * @return string
  558. */
  559. public function getGradebookEvaluationListToString($userId, $coursesAndSessions)
  560. {
  561. $list = $this->getGradebookEvaluationList($userId, $coursesAndSessions);
  562. $html = '';
  563. if (!empty($list)) {
  564. $html = implode('&nbsp;', array_column($list, 'name'));
  565. }
  566. return $html;
  567. }
  568. /**
  569. * @param int $userId
  570. * @param array $coursesAndSessions
  571. *
  572. * @return array
  573. */
  574. public function getGradebookEvaluationList($userId, $coursesAndSessions)
  575. {
  576. $userId = (int) $userId;
  577. if (empty($coursesAndSessions)) {
  578. return 0;
  579. }
  580. $courseSessionConditionToString = '';
  581. foreach ($coursesAndSessions as $sessionId => $courseList) {
  582. if (isset($courseList['course_list'])) {
  583. $courseList = array_keys($courseList['course_list']);
  584. }
  585. if (empty($courseList)) {
  586. continue;
  587. }
  588. //$courseListToString = implode("','", $courseList);
  589. /*if (empty($sessionId)) {
  590. $courseAndSessionCondition[] =
  591. " c.id IN ('$courseListToString') ";
  592. } else {
  593. $courseAndSessionCondition[] = "
  594. (
  595. c.id IN ('$courseListToString')
  596. )";
  597. }*/
  598. $courseSessionConditionToString = " AND c.id IN ('".implode("','", $courseList)."') ";
  599. }
  600. if (empty($courseSessionConditionToString)) {
  601. return 0;
  602. }
  603. $tableEvaluation = Database::get_main_table(TABLE_MAIN_GRADEBOOK_EVALUATION);
  604. $tableCourse = Database::get_main_table(TABLE_MAIN_COURSE);
  605. $tableResult = Database::get_main_table(TABLE_MAIN_GRADEBOOK_RESULT);
  606. $sql = "SELECT DISTINCT e.name, e.id
  607. FROM $tableEvaluation e
  608. INNER JOIN $tableCourse c
  609. ON (course_code = c.code)
  610. INNER JOIN $tableResult r
  611. ON (r.evaluation_id = e.id)
  612. WHERE
  613. e.type = 'evaluation' AND
  614. r.score >= 2 AND
  615. r.user_id = $userId
  616. $courseSessionConditionToString
  617. ";
  618. $result = Database::query($sql);
  619. $list = [];
  620. if (Database::num_rows($result)) {
  621. while ($row = Database::fetch_array($result, 'ASSOC')) {
  622. $list[$row['id']] = $row;
  623. }
  624. }
  625. return $list;
  626. }
  627. /**
  628. * @param int $userId
  629. * @param array $coursesAndSessions
  630. *
  631. * @return int
  632. */
  633. public function getItemCountChecked($userId, $coursesAndSessions)
  634. {
  635. $userId = (int) $userId;
  636. if (empty($coursesAndSessions)) {
  637. return 0;
  638. }
  639. $tableItem = Database::get_course_table(TABLE_LP_ITEM);
  640. $tableLp = Database::get_course_table(TABLE_LP_MAIN);
  641. $tableLpItemView = Database::get_course_table(TABLE_LP_ITEM_VIEW);
  642. $tableLpView = Database::get_course_table(TABLE_LP_VIEW);
  643. $extraField = new ExtraField('lp_item');
  644. $fieldInfo = $extraField->get_handler_field_info_by_field_variable('calendar');
  645. if (empty($fieldInfo)) {
  646. return 0;
  647. }
  648. $courseAndSessionCondition = [];
  649. foreach ($coursesAndSessions as $sessionId => $courseList) {
  650. if (isset($courseList['course_list'])) {
  651. $courseList = array_keys($courseList['course_list']);
  652. }
  653. if (empty($courseList)) {
  654. continue;
  655. }
  656. $courseListToString = implode("','", $courseList);
  657. if (empty($sessionId)) {
  658. $courseAndSessionCondition[] =
  659. " ((l.session_id = 0 OR l.session_id is NULL) AND i.c_id IN ('$courseListToString'))";
  660. } else {
  661. $courseAndSessionCondition[] = "
  662. (
  663. ((l.session_id = 0 OR l.session_id is NULL) OR l.session_id = $sessionId) AND
  664. i.c_id IN ('$courseListToString')
  665. )";
  666. }
  667. }
  668. if (empty($courseAndSessionCondition)) {
  669. return 0;
  670. }
  671. $courseSessionConditionToString = 'AND ('.implode(' OR ', $courseAndSessionCondition).') ';
  672. $sql = "SELECT count(*) as count
  673. FROM $tableItem i INNER JOIN $tableLp l
  674. ON (i.c_id = l.c_id AND i.lp_id = l.iid)
  675. INNER JOIN $tableLpItemView iv
  676. ON (iv.c_id = l.c_id AND i.iid = iv.lp_item_id)
  677. INNER JOIN $tableLpView v
  678. ON (v.c_id = l.c_id AND v.lp_id = l.iid AND iv.lp_view_id = v.iid)
  679. INNER JOIN extra_field_values e
  680. ON (e.item_id = i.iid AND value = 1 AND field_id = ".$fieldInfo['id'].")
  681. WHERE
  682. v.user_id = $userId AND
  683. status = 'completed'
  684. $courseSessionConditionToString
  685. GROUP BY iv.view_count
  686. ";
  687. $result = Database::query($sql);
  688. if (Database::num_rows($result)) {
  689. $row = Database::fetch_array($result, 'ASSOC');
  690. return $row['count'];
  691. }
  692. return 0;
  693. }
  694. /**
  695. * @param array $htmlHeadXtra
  696. */
  697. public function setJavaScript(&$htmlHeadXtra)
  698. {
  699. $htmlHeadXtra[] = api_get_js('jqplot/jquery.jqplot.js');
  700. $htmlHeadXtra[] = api_get_js('jqplot/plugins/jqplot.dateAxisRenderer.js');
  701. $htmlHeadXtra[] = api_get_js('jqplot/plugins/jqplot.canvasOverlay.js');
  702. $htmlHeadXtra[] = api_get_js('jqplot/plugins/jqplot.pointLabels.js');
  703. $htmlHeadXtra[] = api_get_css(api_get_path(WEB_LIBRARY_PATH).'javascript/jqplot/jquery.jqplot.css');
  704. }
  705. /**
  706. * @param int $userId
  707. * @param array $courseAndSessionList
  708. *
  709. * @return string
  710. */
  711. public function getUserStatsPanel($userId, $courseAndSessionList)
  712. {
  713. // @todo use translation
  714. // get events from this year to today
  715. $stats = $this->getUserStats($userId, $courseAndSessionList);
  716. $html = $this->get_lang('Number of days accumulated in calendar').$stats['user_event_count'];
  717. if (!empty($courseAndSessionList)) {
  718. $html .= '<br />';
  719. $html .= $this->get_lang('NumberDaysAccumulatedInLp').$stats['completed'];
  720. $html .= '<br />';
  721. $html .= $this->get_lang('NumberDaysInRetard').' '.($stats['completed'] - $stats['user_event_count']);
  722. }
  723. $controlList = $this->getControlPointsToPlot($userId);
  724. if (!empty($controlList)) {
  725. $listToString = json_encode($controlList);
  726. $date = $this->get_lang('Date');
  727. $controlPoint = $this->get_lang('NumberOfDays');
  728. $html .= '<div id="control_point_chart"></div>';
  729. $html .= '<script>
  730. $(document).ready(function(){
  731.    var cosPoints = '.$listToString.';
  732.    var plot1 = $.jqplot(\'control_point_chart\', [cosPoints], { 
  733. //animate: !$.jqplot.use_excanvas,
  734.      series:[{
  735. showMarker:true,
  736.     pointLabels: { show:true },
  737. }],
  738.        axes:{
  739.         xaxis:{
  740.            label: "'.$date.'",
  741. renderer: $.jqplot.DateAxisRenderer,
  742. tickOptions:{formatString: "%Y-%m-%d"},
  743. tickInterval: \'30 day\',
  744.         },
  745. yaxis:{
  746.            label: "'.$controlPoint.'",
  747. max: 20,
  748. min: -20,
  749.         }
  750.        },
  751. canvasOverlay: {
  752. show: true,
  753. objects: [{
  754. horizontalLine: {
  755. name: \'0 mark\',
  756. y: 0,
  757. lineWidth: 2,
  758. color: \'rgb(f, f, f)\',
  759. shadow: false
  760. }
  761. }]
  762. },
  763.   });
  764. });
  765. </script>';
  766. }
  767. $html = Display::panel($html, $this->get_lang('Learning calendar'));
  768. return $html;
  769. }
  770. /**
  771. * @param int $userId
  772. * @param array $courseAndSessionList
  773. *
  774. * @return array
  775. */
  776. public function getUserStats($userId, $courseAndSessionList)
  777. {
  778. // Get events from this year to today
  779. $takenCount = $this->getUserEvents(
  780. $userId,
  781. strtotime(date('Y-01-01')),
  782. time(),
  783. self::EVENT_TYPE_TAKEN,
  784. true
  785. );
  786. $completed = 0;
  787. $diff = 0;
  788. if (!empty($courseAndSessionList)) {
  789. $completed = $this->getItemCountChecked($userId, $courseAndSessionList);
  790. $diff = $takenCount - $completed;
  791. }
  792. return [
  793. 'user_event_count' => $takenCount,
  794. 'completed' => $completed,
  795. 'diff' => $diff,
  796. ];
  797. }
  798. /**
  799. * @param int $calendarId
  800. *
  801. * @return bool
  802. */
  803. public function copyCalendar($calendarId)
  804. {
  805. $item = $this->getCalendar($calendarId);
  806. $this->protectCalendar($item);
  807. $item['author_id'] = api_get_user_id();
  808. if (empty($item)) {
  809. return false;
  810. }
  811. $calendarId = (int) $calendarId;
  812. unset($item['id']);
  813. //$item['title'] = $item['title'];
  814. $newCalendarId = Database::insert('learning_calendar', $item);
  815. if (!empty($newCalendarId)) {
  816. $sql = "SELECT * FROM learning_calendar_events WHERE calendar_id = $calendarId";
  817. $result = Database::query($sql);
  818. while ($row = Database::fetch_array($result, 'ASSOC')) {
  819. unset($row['id']);
  820. $row['calendar_id'] = $newCalendarId;
  821. Database::insert('learning_calendar_events', $row);
  822. }
  823. return true;
  824. }
  825. return false;
  826. }
  827. /**
  828. * @param int $calendarId
  829. *
  830. * @return bool
  831. */
  832. public function deleteCalendar($calendarId)
  833. {
  834. $item = $this->getCalendar($calendarId);
  835. $this->protectCalendar($item);
  836. if (empty($item)) {
  837. return false;
  838. }
  839. $calendarId = (int) $calendarId;
  840. $sql = "DELETE FROM learning_calendar WHERE id = $calendarId";
  841. Database::query($sql);
  842. // Delete events
  843. $sql = "DELETE FROM learning_calendar_events WHERE calendar_id = $calendarId";
  844. Database::query($sql);
  845. return true;
  846. }
  847. /**
  848. * @param int $calendarId
  849. * @param string $startDate
  850. */
  851. public function toogleDayType($calendarId, $startDate)
  852. {
  853. $startDate = Database::escape_string($startDate);
  854. $calendarId = (int) $calendarId;
  855. $eventTypeList = $this->getEventTypeColorList();
  856. // Remove the free type to loop correctly when toogle days.
  857. unset($eventTypeList[self::EVENT_TYPE_FREE]);
  858. $sql = "SELECT * FROM learning_calendar_events
  859. WHERE start_date = '$startDate' AND calendar_id = $calendarId ";
  860. $result = Database::query($sql);
  861. if (Database::num_rows($result)) {
  862. $row = Database::fetch_array($result, 'ASSOC');
  863. $currentType = $row['type'];
  864. $currentType++;
  865. if ($currentType > count($eventTypeList)) {
  866. Database::delete(
  867. 'learning_calendar_events',
  868. [' calendar_id = ? AND start_date = ?' => [$calendarId, $startDate]]
  869. );
  870. } else {
  871. $params = [
  872. 'type' => $currentType,
  873. ];
  874. Database::update(
  875. 'learning_calendar_events',
  876. $params,
  877. [' calendar_id = ? AND start_date = ?' => [$calendarId, $startDate]]
  878. );
  879. }
  880. } else {
  881. $params = [
  882. 'name' => '',
  883. 'calendar_id' => $calendarId,
  884. 'start_date' => $startDate,
  885. 'end_date' => $startDate,
  886. 'type' => self::EVENT_TYPE_TAKEN,
  887. ];
  888. Database::insert('learning_calendar_events', $params);
  889. }
  890. }
  891. /**
  892. * @param int $calendarId
  893. *
  894. * @return array
  895. */
  896. public function getEvents($calendarId)
  897. {
  898. $calendarId = (int) $calendarId;
  899. $eventTypeList = $this->getEventTypeColorList();
  900. $sql = "SELECT * FROM learning_calendar_events
  901. WHERE calendar_id = $calendarId ";
  902. $result = Database::query($sql);
  903. $list = [];
  904. while ($row = Database::fetch_array($result, 'ASSOC')) {
  905. $list[] = [
  906. 'start_date' => $row['start_date'],
  907. 'end_date' => $row['start_date'],
  908. 'color' => $eventTypeList[$row['type']],
  909. ];
  910. }
  911. return $list;
  912. }
  913. /**
  914. * @param array $calendarInfo
  915. */
  916. public function protectCalendar(array $calendarInfo)
  917. {
  918. $allow = api_is_platform_admin() || api_is_teacher();
  919. if (!$allow) {
  920. api_not_allowed(true);
  921. }
  922. if (!empty($calendarInfo)) {
  923. if (!api_is_platform_admin() && api_is_teacher()) {
  924. if ($calendarInfo['author_id'] != api_get_user_id()) {
  925. api_not_allowed(true);
  926. }
  927. }
  928. }
  929. }
  930. /**
  931. * @param int $userId
  932. *
  933. * @return array
  934. */
  935. public function getControlPoints($userId)
  936. {
  937. $userId = (int) $userId;
  938. $sql = "SELECT control_date, control_value
  939. FROM learning_calendar_control_point
  940. WHERE user_id = $userId
  941. ORDER BY control_date";
  942. $result = Database::query($sql);
  943. $list = Database::store_result($result, 'ASSOC');
  944. return $list;
  945. }
  946. /**
  947. * @param int $userId
  948. *
  949. * @return array
  950. */
  951. public function getControlPointsToPlot($userId)
  952. {
  953. $list = $this->getControlPoints($userId);
  954. $points = [];
  955. foreach ($list as $item) {
  956. $points[] = [$item['control_date'], $item['control_value']];
  957. }
  958. return $points;
  959. }
  960. /**
  961. * @param int $userId
  962. * @param int $value
  963. */
  964. public function addControlPoint($userId, $value)
  965. {
  966. $userId = (int) $userId;
  967. $value = (int) $value;
  968. $local = api_get_local_time();
  969. $date = substr($local, 0, 10);
  970. $sql = "SELECT id
  971. FROM learning_calendar_control_point
  972. WHERE user_id = $userId AND control_date = '$date'";
  973. $result = Database::query($sql);
  974. if (Database::num_rows($result)) {
  975. $params = [
  976. 'control_value' => $value,
  977. 'updated_at' => api_get_utc_datetime(),
  978. ];
  979. $data = Database::fetch_array($result);
  980. $id = $data['id'];
  981. Database::update('learning_calendar_control_point', $params, ['id = ?' => $id]);
  982. } else {
  983. $params = [
  984. 'user_id' => $userId,
  985. 'control_date' => $date,
  986. 'control_value' => $value,
  987. 'created_at' => api_get_utc_datetime(),
  988. 'updated_at' => api_get_utc_datetime(),
  989. ];
  990. Database::insert('learning_calendar_control_point', $params);
  991. }
  992. }
  993. /**
  994. * @param FormValidator $form
  995. */
  996. public function getAddUserToCalendarForm(FormValidator &$form)
  997. {
  998. $calendars = $this->getCalendars(0, 1000, '');
  999. if (empty($calendars)) {
  1000. echo Display::return_message(get_lang('No data available'), 'warning');
  1001. exit;
  1002. }
  1003. $calendars = array_column($calendars, 'title', 'id');
  1004. $calendars = array_map('strip_tags', $calendars);
  1005. $form->addSelect('calendar_id', get_lang('Calendar'), $calendars, ['disable_js' => true]);
  1006. }
  1007. }