ScheduledAnnouncement.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. /**
  4. * Class ScheduledAnnouncement
  5. * Requires DB change:.
  6. *
  7. * CREATE TABLE scheduled_announcements (id INT AUTO_INCREMENT NOT NULL, subject VARCHAR(255) NOT NULL, message LONGTEXT NOT NULL, date DATETIME DEFAULT NULL, sent TINYINT(1) NOT NULL, session_id INT NOT NULL, c_id INT DEFAULT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
  8. *
  9. * Config setting:
  10. * $_configuration['allow_scheduled_announcements'] = true;
  11. *
  12. * Setup linux cron file:
  13. * main/cron/scheduled_announcement.php
  14. *
  15. * Requires:
  16. * composer update
  17. *
  18. * @package chamilo.library
  19. */
  20. class ScheduledAnnouncement extends Model
  21. {
  22. public $table;
  23. public $columns = ['id', 'subject', 'message', 'date', 'sent', 'session_id'];
  24. /**
  25. * Constructor.
  26. */
  27. public function __construct()
  28. {
  29. parent::__construct();
  30. $this->table = 'scheduled_announcements';
  31. }
  32. /**
  33. * @param array $where_conditions
  34. *
  35. * @return array
  36. */
  37. public function get_all($where_conditions = [])
  38. {
  39. return Database::select(
  40. '*',
  41. $this->table,
  42. ['where' => $where_conditions, 'order' => 'subject ASC']
  43. );
  44. }
  45. /**
  46. * @return mixed
  47. */
  48. public function get_count()
  49. {
  50. $row = Database::select(
  51. 'count(*) as count',
  52. $this->table,
  53. [],
  54. 'first'
  55. );
  56. return $row['count'];
  57. }
  58. /**
  59. * Displays the title + grid.
  60. *
  61. * @param int $sessionId
  62. *
  63. * @return string
  64. */
  65. public function getGrid($sessionId)
  66. {
  67. // action links
  68. $action = '<div class="actions" style="margin-bottom:20px">';
  69. $action .= Display::url(
  70. Display::return_icon('back.png', get_lang('Back'), '', ICON_SIZE_MEDIUM),
  71. api_get_path(WEB_CODE_PATH).'session/resume_session.php?id_session='.$sessionId
  72. );
  73. $action .= '<a href="'.api_get_self().'?action=add&session_id='.$sessionId.'">'.
  74. Display::return_icon('add.png', get_lang('Add'), '', ICON_SIZE_MEDIUM).'</a>';
  75. $action .= '<a href="scheduled_announcement.php?action=run&session_id='.$sessionId.'">'.
  76. Display::return_icon('tuning.png', get_lang('Send pending announcements manually'), '', ICON_SIZE_MEDIUM).
  77. '</a>';
  78. $action .= '</div>';
  79. $html = $action;
  80. $html .= '<div id="session-table" class="table-responsive">';
  81. $html .= Display::grid_html('programmed');
  82. $html .= '</div>';
  83. return $html;
  84. }
  85. /**
  86. * Returns a Form validator Obj.
  87. *
  88. * @param int $id
  89. * @param string $url
  90. * @param string $action add, edit
  91. * @param array $sessionInfo
  92. *
  93. * @return FormValidator form validator obj
  94. */
  95. public function returnSimpleForm($id, $url, $action, $sessionInfo = [])
  96. {
  97. $form = new FormValidator(
  98. 'announcement',
  99. 'post',
  100. $url
  101. );
  102. $form->addHidden('session_id', $sessionInfo['id']);
  103. $form->addDateTimePicker('date', get_lang('Date'));
  104. $form->addText('subject', get_lang('Subject'));
  105. $form->addHtmlEditor('message', get_lang('Message'));
  106. $extraField = new ExtraField('scheduled_announcement');
  107. $extra = $extraField->addElements($form, $id);
  108. $js = $extra['jquery_ready_content'];
  109. $form->addHtml("<script> $(function() { $js }); </script> ");
  110. $this->setTagsInForm($form);
  111. $form->addCheckBox('sent', null, get_lang('Message Sent'));
  112. if ($action == 'edit') {
  113. $form->addButtonUpdate(get_lang('Edit'));
  114. }
  115. return $form;
  116. }
  117. /**
  118. * Returns a Form validator Obj.
  119. *
  120. * @todo the form should be auto generated
  121. *
  122. * @param string $url
  123. * @param string $action add, edit
  124. * @param array
  125. *
  126. * @return FormValidator form validator obj
  127. */
  128. public function returnForm($url, $action, $sessionInfo = [])
  129. {
  130. // Setting the form elements
  131. $header = get_lang('Add');
  132. if ($action == 'edit') {
  133. $header = get_lang('Edit');
  134. }
  135. $form = new FormValidator(
  136. 'announcement',
  137. 'post',
  138. $url
  139. );
  140. $form->addHeader($header);
  141. if ($action == 'add') {
  142. $form->addHtml(
  143. Display::return_message(
  144. nl2br(get_lang('This form allows scheduling announcements to be sent automatically to the students who are taking a course in a session.')),
  145. 'normal',
  146. false
  147. )
  148. );
  149. }
  150. $form->addHidden('session_id', $sessionInfo['id']);
  151. $useBaseDate = false;
  152. $startDate = $sessionInfo['access_start_date'];
  153. $endDate = $sessionInfo['access_end_date'];
  154. if (!empty($startDate) || !empty($endDate)) {
  155. $useBaseDate = true;
  156. }
  157. $typeOptions = [
  158. 'specific_date' => get_lang('Specific dispatch date'),
  159. ];
  160. if ($useBaseDate) {
  161. $typeOptions['base_date'] = get_lang('BaseDate');
  162. }
  163. $form->addSelect(
  164. 'type',
  165. get_lang('Type'),
  166. $typeOptions,
  167. [
  168. 'onchange' => "javascript:
  169. if (this.options[this.selectedIndex].value == 'base_date') {
  170. document.getElementById('options').style.display = 'block';
  171. document.getElementById('specific_date').style.display = 'none';
  172. } else {
  173. document.getElementById('options').style.display = 'none';
  174. document.getElementById('specific_date').style.display = 'block';
  175. }
  176. ", ]
  177. );
  178. $form->addHtml('<div id="specific_date">');
  179. $form->addDateTimePicker('date', get_lang('Date'));
  180. $form->addHtml('</div>');
  181. $form->addHtml('<div id="options" style="display:none">');
  182. $startDate = $sessionInfo['access_start_date'];
  183. $endDate = $sessionInfo['access_end_date'];
  184. $form->addText(
  185. 'days',
  186. get_lang('days'),
  187. false
  188. );
  189. $form->addSelect(
  190. 'moment_type',
  191. get_lang('After or before'),
  192. [
  193. 'after' => get_lang('After'),
  194. 'before' => get_lang('Before'),
  195. ]
  196. );
  197. if (!empty($startDate)) {
  198. $options['start_date'] = get_lang('Start Date').' - '.$startDate;
  199. }
  200. if (!empty($endDate)) {
  201. $options['end_date'] = get_lang('End Date').' - '.$endDate;
  202. }
  203. if (!empty($options)) {
  204. $form->addSelect('base_date', get_lang('Dispatch based on the session\'s start/end dates'), $options);
  205. }
  206. $form->addHtml('</div>');
  207. $form->addText('subject', get_lang('Subject'));
  208. $form->addHtmlEditor('message', get_lang('Message'));
  209. $extraField = new ExtraField('scheduled_announcement');
  210. $extra = $extraField->addElements($form);
  211. $js = $extra['jquery_ready_content'];
  212. $form->addHtml("<script> $(function() { $js }); </script> ");
  213. $this->setTagsInForm($form);
  214. if ($action == 'edit') {
  215. $form->addButtonUpdate(get_lang('Edit'));
  216. } else {
  217. $form->addButtonCreate(get_lang('Add'));
  218. }
  219. return $form;
  220. }
  221. /**
  222. * @param int $id
  223. *
  224. * @return string
  225. */
  226. public function getAttachmentToString($id)
  227. {
  228. $file = $this->getAttachment($id);
  229. if (!empty($file) && !empty($file['value'])) {
  230. $url = api_get_path(WEB_UPLOAD_PATH).$file['value'];
  231. return get_lang('Attachment').': '.Display::url(basename($file['value']), $url, ['target' => '_blank']);
  232. }
  233. return '';
  234. }
  235. /**
  236. * @param int $id
  237. *
  238. * @return array
  239. */
  240. public function getAttachment($id)
  241. {
  242. $extraFieldValue = new ExtraFieldValue('scheduled_announcement');
  243. $attachment = $extraFieldValue->get_values_by_handler_and_field_variable($id, 'attachment');
  244. return $attachment;
  245. }
  246. /**
  247. * @param int $urlId
  248. *
  249. * @return int
  250. */
  251. public function sendPendingMessages($urlId = 0)
  252. {
  253. if (!$this->allowed()) {
  254. return 0;
  255. }
  256. $messagesSent = 0;
  257. $now = api_get_utc_datetime();
  258. $result = $this->get_all();
  259. $extraFieldValue = new ExtraFieldValue('scheduled_announcement');
  260. foreach ($result as $result) {
  261. if (empty($result['sent'])) {
  262. if (!empty($result['date']) && $result['date'] < $now) {
  263. $sessionId = $result['session_id'];
  264. $sessionInfo = api_get_session_info($sessionId);
  265. if (empty($sessionInfo)) {
  266. continue;
  267. }
  268. $users = SessionManager::get_users_by_session(
  269. $sessionId,
  270. 0,
  271. false,
  272. $urlId
  273. );
  274. $coachId = $sessionInfo['id_coach'];
  275. if (empty($users) || empty($coachId)) {
  276. continue;
  277. }
  278. if ($users) {
  279. $sendToCoaches = $extraFieldValue->get_values_by_handler_and_field_variable($result['id'], 'send_to_coaches');
  280. $courseList = SessionManager::getCoursesInSession($sessionId);
  281. $coachList = [];
  282. if (!empty($sendToCoaches) && !empty($sendToCoaches['value']) && $sendToCoaches['value'] == 1) {
  283. foreach ($courseList as $courseItemId) {
  284. $coaches = SessionManager::getCoachesByCourseSession(
  285. $sessionId,
  286. $courseItemId
  287. );
  288. $coachList = array_merge($coachList, $coaches);
  289. }
  290. $coachList = array_unique($coachList);
  291. }
  292. $this->update(['id' => $result['id'], 'sent' => 1]);
  293. $attachments = $this->getAttachmentToString($result['id']);
  294. $subject = $result['subject'];
  295. $courseInfo = [];
  296. if (!empty($courseList)) {
  297. $courseId = current($courseList);
  298. $courseInfo = api_get_course_info_by_id($courseId);
  299. }
  300. foreach ($users as $user) {
  301. // Take original message
  302. $message = $result['message'];
  303. $userInfo = api_get_user_info($user['user_id']);
  304. $progress = '';
  305. if (!empty($sessionInfo) && !empty($courseInfo)) {
  306. $progress = Tracking::get_avg_student_progress(
  307. $user['user_id'],
  308. $courseInfo['code'],
  309. [],
  310. $sessionId
  311. );
  312. }
  313. if (is_numeric($progress)) {
  314. $progress = $progress.'%';
  315. } else {
  316. $progress = '0%';
  317. }
  318. $startTime = api_get_local_time(
  319. $sessionInfo['access_start_date'],
  320. null,
  321. null,
  322. true
  323. );
  324. $endTime = api_get_local_time(
  325. $sessionInfo['access_end_date'],
  326. null,
  327. null,
  328. true
  329. );
  330. $generalCoach = '';
  331. $generalCoachEmail = '';
  332. if (!empty($sessionInfo['id_coach'])) {
  333. $coachInfo = api_get_user_info($sessionInfo['id_coach']);
  334. if (!empty($coachInfo)) {
  335. $generalCoach = $coachInfo['complete_name'];
  336. $generalCoachEmail = $coachInfo['email'];
  337. }
  338. }
  339. $tags = [
  340. '((session_name))' => $sessionInfo['name'],
  341. '((session_start_date))' => $startTime,
  342. '((general_coach))' => $generalCoach,
  343. '((general_coach_email))' => $generalCoachEmail,
  344. '((session_end_date))' => $endTime,
  345. '((user_complete_name))' => $userInfo['complete_name'],
  346. '((user_first_name))' => $userInfo['firstname'],
  347. '((user_last_name))' => $userInfo['lastname'],
  348. '((lp_progress))' => $progress,
  349. ];
  350. $message = str_replace(array_keys($tags), $tags, $message);
  351. $message .= $attachments;
  352. MessageManager::send_message_simple(
  353. $userInfo['user_id'],
  354. $subject,
  355. $message,
  356. $coachId
  357. );
  358. }
  359. $message = get_lang('You\'re receiving a copy because, you\'re a course coach').'<br /><br />'.$message;
  360. foreach ($coachList as $courseCoachId) {
  361. MessageManager::send_message_simple(
  362. $courseCoachId,
  363. get_lang('You\'re receiving a copy because, you\'re a course coach').'&nbsp;'.$subject,
  364. $message,
  365. $coachId
  366. );
  367. }
  368. }
  369. $messagesSent++;
  370. }
  371. }
  372. }
  373. return $messagesSent;
  374. }
  375. /**
  376. * @return array
  377. */
  378. public function getTags()
  379. {
  380. $tags = [
  381. '((session_name))',
  382. '((session_start_date))',
  383. '((session_end_date))',
  384. '((general_coach))',
  385. '((general_coach_email))',
  386. '((user_complete_name))',
  387. '((user_first_name))',
  388. '((user_last_name))',
  389. '((lp_progress))',
  390. ];
  391. return $tags;
  392. }
  393. /**
  394. * @return bool
  395. */
  396. public function allowed()
  397. {
  398. return api_get_configuration_value('allow_scheduled_announcements');
  399. }
  400. /**
  401. * @param FormValidator $form
  402. */
  403. private function setTagsInForm(&$form)
  404. {
  405. $form->addLabel(
  406. get_lang('Tags'),
  407. Display::return_message(
  408. implode('<br />', $this->getTags()),
  409. 'normal',
  410. false
  411. )
  412. );
  413. }
  414. }