system_announcements.lib.php 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. /**
  4. * Class SystemAnnouncementManager.
  5. */
  6. class SystemAnnouncementManager
  7. {
  8. public const VISIBLE_GUEST = 'visible_guest';
  9. public const VISIBLE_STUDENT = 'visible_student';
  10. public const VISIBLE_TEACHER = 'visible_teacher';
  11. public const VISIBLE_DRH = 'visible_drh';
  12. public const VISIBLE_SESSION_ADMIN = 'visible_session_admin';
  13. public const VISIBLE_STUDENT_BOSS = 'visible_boss';
  14. /**
  15. * @return array
  16. */
  17. public static function getVisibilityList(): array
  18. {
  19. $visibleToUsers = [
  20. self::VISIBLE_TEACHER => get_lang('Trainer'),
  21. self::VISIBLE_STUDENT => get_lang('Learner'),
  22. self::VISIBLE_GUEST => get_lang('Guest'),
  23. ];
  24. $visibleToUsers[self::VISIBLE_DRH] = get_lang('Human Resources Manager');
  25. $visibleToUsers[self::VISIBLE_SESSION_ADMIN] = get_lang('Session administrator');
  26. $visibleToUsers[self::VISIBLE_STUDENT_BOSS] = get_lang('LearnerBoss');
  27. return $visibleToUsers;
  28. }
  29. /**
  30. * @param string $visibility
  31. *
  32. * @return string
  33. */
  34. public static function getVisibilityCondition($visibility)
  35. {
  36. $list = self::getVisibilityList();
  37. $visibilityCondition = " AND ".self::VISIBLE_GUEST." = 1 ";
  38. if (in_array($visibility, array_keys($list))) {
  39. $visibilityCondition = " AND $visibility = 1 ";
  40. }
  41. return $visibilityCondition;
  42. }
  43. /**
  44. * Displays all announcements.
  45. *
  46. * @param string $visibility VISIBLE_GUEST, VISIBLE_STUDENT or VISIBLE_TEACHER
  47. * @param int $id The identifier of the announcement to display
  48. */
  49. public static function display_announcements($visibility, $id = -1)
  50. {
  51. $user_selected_language = api_get_interface_language();
  52. $db_table = Database::get_main_table(TABLE_MAIN_SYSTEM_ANNOUNCEMENTS);
  53. $tbl_announcement_group = Database::get_main_table(TABLE_MAIN_SYSTEM_ANNOUNCEMENTS_GROUPS);
  54. $userGroup = new UserGroup();
  55. $temp_user_groups = $userGroup->get_groups_by_user(api_get_user_id(), 0);
  56. $groups = [];
  57. foreach ($temp_user_groups as $user_group) {
  58. $groups = array_merge($groups, [$user_group['id']]);
  59. $groups = array_merge(
  60. $groups,
  61. $userGroup->get_parent_groups($user_group['id'])
  62. );
  63. }
  64. $groups_string = '('.implode($groups, ',').')';
  65. $now = api_get_utc_datetime();
  66. $sql = "SELECT *, DATE_FORMAT(date_start,'%d-%m-%Y %h:%i:%s') AS display_date
  67. FROM $db_table
  68. WHERE
  69. (lang='$user_selected_language' OR lang IS NULL) AND
  70. (('$now' BETWEEN date_start AND date_end) OR date_end='0000-00-00') ";
  71. $sql .= self::getVisibilityCondition($visibility);
  72. if (count($groups) > 0) {
  73. $sql .= " OR id IN (
  74. SELECT announcement_id FROM $tbl_announcement_group
  75. WHERE group_id in $groups_string
  76. ) ";
  77. }
  78. $current_access_url_id = 1;
  79. if (api_is_multiple_url_enabled()) {
  80. $current_access_url_id = api_get_current_access_url_id();
  81. }
  82. $sql .= " AND access_url_id = '$current_access_url_id' ";
  83. $sql .= " ORDER BY date_start DESC LIMIT 0,7";
  84. $announcements = Database::query($sql);
  85. if (Database::num_rows($announcements) > 0) {
  86. $query_string = ereg_replace('announcement=[1-9]+', '', $_SERVER['QUERY_STRING']);
  87. $query_string = ereg_replace('&$', '', $query_string);
  88. $url = api_get_self();
  89. echo '<div class="system_announcements">';
  90. echo '<h3>'.get_lang('Portal news').'</h3>';
  91. echo '<div style="margin:10px;text-align:right;"><a href="news_list.php">'.get_lang('More').'</a></div>';
  92. while ($announcement = Database::fetch_object($announcements)) {
  93. if ($id != $announcement->id) {
  94. if (strlen($query_string) > 0) {
  95. $show_url = 'news_list.php#'.$announcement->id;
  96. } else {
  97. $show_url = 'news_list.php#'.$announcement->id;
  98. }
  99. $display_date = api_convert_and_format_date($announcement->display_date, DATE_FORMAT_LONG);
  100. echo '<a name="'.$announcement->id.'"></a>
  101. <div class="system_announcement">
  102. <div class="system_announcement_title">
  103. <a name="ann'.$announcement->id.'" href="'.$show_url.'">'.
  104. $announcement->title.'</a>
  105. </div>
  106. <div class="system_announcement_date">'.$display_date.'</div>
  107. </div>';
  108. } else {
  109. echo '<div class="system_announcement">
  110. <div class="system_announcement_title">'
  111. .$announcement->display_date.'
  112. <a name="ann'.$announcement->id.'" href="'.$url.'?'.$query_string.'#ann'.$announcement->id.'">'.
  113. $announcement->title.'
  114. </a>
  115. </div>';
  116. }
  117. echo '<br />';
  118. }
  119. echo '</div>';
  120. }
  121. }
  122. /**
  123. * @param string $visibility
  124. * @param int $id
  125. * @param int $start
  126. * @param string $user_id
  127. *
  128. * @return string
  129. */
  130. public static function displayAllAnnouncements(
  131. $visibility,
  132. $id = -1,
  133. $start = 0,
  134. $user_id = ''
  135. ) {
  136. $user_selected_language = api_get_interface_language();
  137. $start = intval($start);
  138. $userGroup = new UserGroup();
  139. $tbl_announcement_group = Database::get_main_table(TABLE_MAIN_SYSTEM_ANNOUNCEMENTS_GROUPS);
  140. $temp_user_groups = $userGroup->get_groups_by_user(api_get_user_id(), 0);
  141. $groups = [];
  142. foreach ($temp_user_groups as $user_group) {
  143. $groups = array_merge($groups, [$user_group['id']]);
  144. $groups = array_merge($groups, $userGroup->get_parent_groups($user_group['id']));
  145. }
  146. // Checks if tables exists to not break platform not updated
  147. $groups_string = '('.implode($groups, ',').')';
  148. $table = Database::get_main_table(TABLE_MAIN_SYSTEM_ANNOUNCEMENTS);
  149. $now = api_get_utc_datetime();
  150. $sql = "SELECT * FROM $table
  151. WHERE
  152. (lang = '$user_selected_language' OR lang IS NULL) AND
  153. ( '$now' >= date_start AND '$now' <= date_end) ";
  154. $sql .= self::getVisibilityCondition($visibility);
  155. if (count($groups) > 0) {
  156. $sql .= " OR id IN (
  157. SELECT announcement_id FROM $tbl_announcement_group
  158. WHERE group_id in $groups_string
  159. ) ";
  160. }
  161. if (api_is_multiple_url_enabled()) {
  162. $current_access_url_id = api_get_current_access_url_id();
  163. $sql .= " AND access_url_id IN ('1', '$current_access_url_id')";
  164. }
  165. if (!isset($_GET['start']) || $_GET['start'] == 0) {
  166. $sql .= " ORDER BY date_start DESC LIMIT ".$start.",20";
  167. } else {
  168. $sql .= " ORDER BY date_start DESC LIMIT ".($start + 1).",20";
  169. }
  170. $announcements = Database::query($sql);
  171. $content = '';
  172. if (Database::num_rows($announcements) > 0) {
  173. $content .= '<div class="system_announcements">';
  174. $content .= '<h3>'.get_lang('Portal news').'</h3>';
  175. $content .= '<table align="center">';
  176. $content .= '<tr>';
  177. $content .= '<td>';
  178. $content .= self::display_arrow($user_id);
  179. $content .= '</td>';
  180. $content .= '</tr>';
  181. $content .= '</table>';
  182. $content .= '<table align="center" border="0" width="900px">';
  183. while ($announcement = Database::fetch_object($announcements)) {
  184. $display_date = api_convert_and_format_date($announcement->display_date, DATE_FORMAT_LONG);
  185. $content .= '<tr><td>';
  186. $content .= '<a name="'.$announcement->id.'"></a>
  187. <div class="system_announcement">
  188. <h2>'.$announcement->title.'</h2>
  189. <div class="system_announcement_date">'.$display_date.'</div>
  190. <br />
  191. <div class="system_announcement_content">'
  192. .$announcement->content.'
  193. </div>
  194. </div><br />';
  195. $content .= '</tr></td>';
  196. }
  197. $content .= '</table>';
  198. $content .= '<table align="center">';
  199. $content .= '<tr>';
  200. $content .= '<td>';
  201. $content .= self::display_arrow($user_id);
  202. $content .= '</td>';
  203. $content .= '</tr>';
  204. $content .= '</table>';
  205. $content .= '</div>';
  206. }
  207. return $content;
  208. }
  209. /**
  210. * @param int $user_id
  211. *
  212. * @return string
  213. */
  214. public static function display_arrow($user_id)
  215. {
  216. $start = (int) $_GET['start'];
  217. $nb_announcement = self::count_nb_announcement($start, $user_id);
  218. $next = ((int) $_GET['start'] + 19);
  219. $prev = ((int) $_GET['start'] - 19);
  220. $content = '';
  221. if (!isset($_GET['start']) || $_GET['start'] == 0) {
  222. if ($nb_announcement > 20) {
  223. $content .= '<a href="news_list.php?start='.$next.'">'.get_lang('Next').' >> </a>';
  224. }
  225. } else {
  226. echo '<a href="news_list.php?start='.$prev.'"> << '.get_lang('Prev').'</a>';
  227. if ($nb_announcement > 20) {
  228. $content .= '<a href="news_list.php?start='.$next.'">'.get_lang('Next').' >> </a>';
  229. }
  230. }
  231. return $content;
  232. }
  233. /**
  234. * Update announcements picture.
  235. *
  236. * @param int $announcement_id
  237. * @param string the full system name of the image
  238. * from which course picture will be created
  239. * @param string $cropParameters Optional string that contents "x,y,width,height" of a cropped image format
  240. *
  241. * @return bool Returns the resulting. In case of internal error or negative validation returns FALSE.
  242. */
  243. public static function update_announcements_picture(
  244. $announcement_id,
  245. $source_file = null,
  246. $cropParameters = null
  247. ) {
  248. if (empty($announcement_id)) {
  249. return false;
  250. }
  251. // course path
  252. $store_path = api_get_path(SYS_UPLOAD_PATH).'announcements';
  253. if (!file_exists($store_path)) {
  254. mkdir($store_path);
  255. }
  256. // image name
  257. $announcementPicture = $store_path.'/announcement_'.$announcement_id.'.png';
  258. $announcementPictureSmall = $store_path.'/announcement_'.$announcement_id.'_100x100.png';
  259. if (file_exists($announcementPicture)) {
  260. unlink($announcementPicture);
  261. }
  262. if (file_exists($announcementPictureSmall)) {
  263. unlink($announcementPictureSmall);
  264. }
  265. //Crop the image to adjust 4:3 ratio
  266. $image = new Image($source_file);
  267. $image->crop($cropParameters);
  268. $medium = new Image($source_file);
  269. $medium->resize(100);
  270. $medium->send_image($announcementPictureSmall, -1, 'png');
  271. $normal = new Image($source_file);
  272. $normal->send_image($announcementPicture, -1, 'png');
  273. $result = $normal;
  274. return $result ? $result : false;
  275. }
  276. /**
  277. * @param int $start
  278. * @param string $user_id
  279. *
  280. * @return int
  281. */
  282. public static function count_nb_announcement($start = 0, $user_id = '')
  283. {
  284. $start = intval($start);
  285. $user_selected_language = api_get_interface_language();
  286. $db_table = Database::get_main_table(TABLE_MAIN_SYSTEM_ANNOUNCEMENTS);
  287. $sql = 'SELECT id FROM '.$db_table.'
  288. WHERE (lang="'.$user_selected_language.'" OR lang IS NULL) ';
  289. $visibility = self::getCurrentUserVisibility();
  290. $sql .= self::getVisibilityCondition($visibility);
  291. $current_access_url_id = 1;
  292. if (api_is_multiple_url_enabled()) {
  293. $current_access_url_id = api_get_current_access_url_id();
  294. }
  295. $sql .= " AND access_url_id = '$current_access_url_id' ";
  296. $sql .= 'LIMIT '.$start.', 21';
  297. $announcements = Database::query($sql);
  298. $i = 0;
  299. while ($rows = Database::fetch_array($announcements)) {
  300. $i++;
  301. }
  302. return $i;
  303. }
  304. /**
  305. * Get all announcements.
  306. *
  307. * @return array An array with all available system announcements (as php
  308. * objects)
  309. */
  310. public static function get_all_announcements()
  311. {
  312. $table = Database::get_main_table(TABLE_MAIN_SYSTEM_ANNOUNCEMENTS);
  313. $now = api_get_utc_datetime();
  314. $sql = "SELECT *, IF ( '$now' >= date_start AND '$now' <= date_end, '1', '0') AS visible
  315. FROM $table";
  316. $current_access_url_id = 1;
  317. if (api_is_multiple_url_enabled()) {
  318. $current_access_url_id = api_get_current_access_url_id();
  319. }
  320. $sql .= " WHERE access_url_id = '$current_access_url_id' ";
  321. $sql .= " ORDER BY date_start ASC";
  322. $result = Database::query($sql);
  323. $announcements = [];
  324. while ($announcement = Database::fetch_object($result)) {
  325. $announcements[] = $announcement;
  326. }
  327. return $announcements;
  328. }
  329. /**
  330. * Adds an announcement to the database.
  331. *
  332. * @param string $title Title of the announcement
  333. * @param string $content Content of the announcement
  334. * @param string $date_start Start date (YYYY-MM-DD HH:II: SS)
  335. * @param string $date_end End date (YYYY-MM-DD HH:II: SS)
  336. * @param array $visibility
  337. * @param string $lang The language for which the announvement should be shown. Leave null for all langages
  338. * @param int $send_mail Whether to send an e-mail to all users (1) or not (0)
  339. * @param bool $add_to_calendar
  340. * @param bool $sendEmailTest
  341. *
  342. * @return mixed insert_id on success, false on failure
  343. */
  344. public static function add_announcement(
  345. $title,
  346. $content,
  347. $date_start,
  348. $date_end,
  349. $visibility,
  350. $lang = '',
  351. $send_mail = 0,
  352. $add_to_calendar = false,
  353. $sendEmailTest = false
  354. ) {
  355. $original_content = $content;
  356. $a_dateS = explode(' ', $date_start);
  357. $a_arraySD = explode('-', $a_dateS[0]);
  358. $a_arraySH = explode(':', $a_dateS[1]);
  359. $date_start_to_compare = array_merge($a_arraySD, $a_arraySH);
  360. $a_dateE = explode(' ', $date_end);
  361. $a_arrayED = explode('-', $a_dateE[0]);
  362. $a_arrayEH = explode(':', $a_dateE[1]);
  363. $date_end_to_compare = array_merge($a_arrayED, $a_arrayEH);
  364. $db_table = Database::get_main_table(TABLE_MAIN_SYSTEM_ANNOUNCEMENTS);
  365. if (!checkdate($date_start_to_compare[1], $date_start_to_compare[2], $date_start_to_compare[0])) {
  366. Display::addFlash(
  367. Display::return_message(get_lang('Invalid start date was given.'), 'warning')
  368. );
  369. return false;
  370. }
  371. if (($date_end_to_compare[1] ||
  372. $date_end_to_compare[2] ||
  373. $date_end_to_compare[0]) &&
  374. !checkdate($date_end_to_compare[1], $date_end_to_compare[2], $date_end_to_compare[0])
  375. ) {
  376. Display::addFlash(
  377. Display::return_message(get_lang('Invalid end date was given.'), 'warning')
  378. );
  379. return false;
  380. }
  381. if (strlen(trim($title)) == 0) {
  382. Display::addFlash(
  383. Display::return_message(get_lang('Please enter a title'), 'warning')
  384. );
  385. return false;
  386. }
  387. $start = api_get_utc_datetime($date_start);
  388. $end = api_get_utc_datetime($date_end);
  389. //Fixing urls that are sent by email
  390. //$content = str_replace('src=\"/home/', 'src=\"'.api_get_path(WEB_PATH).'home/', $content);
  391. //$content = str_replace('file=/home/', 'file='.api_get_path(WEB_PATH).'home/', $content);
  392. $content = str_replace(
  393. 'src=\"'.api_get_path(REL_HOME_PATH),
  394. 'src=\"'.api_get_path(WEB_PATH).api_get_path(REL_HOME_PATH),
  395. $content
  396. );
  397. $content = str_replace(
  398. 'file='.api_get_path(REL_HOME_PATH),
  399. 'file='.api_get_path(WEB_PATH).api_get_path(REL_HOME_PATH),
  400. $content
  401. );
  402. $lang = is_null($lang) ? '' : $lang;
  403. $current_access_url_id = 1;
  404. if (api_is_multiple_url_enabled()) {
  405. $current_access_url_id = api_get_current_access_url_id();
  406. }
  407. $params = [
  408. 'title' => $title,
  409. 'content' => $content,
  410. 'date_start' => $start,
  411. 'date_end' => $end,
  412. 'lang' => $lang,
  413. 'access_url_id' => $current_access_url_id,
  414. ];
  415. foreach ($visibility as $key => $value) {
  416. $params[$key] = $value;
  417. }
  418. $resultId = Database::insert($db_table, $params);
  419. if ($resultId) {
  420. if ($sendEmailTest) {
  421. self::send_system_announcement_by_email(
  422. $title,
  423. $content,
  424. $visibility,
  425. $lang,
  426. true
  427. );
  428. } else {
  429. if ($send_mail == 1) {
  430. self::send_system_announcement_by_email(
  431. $title,
  432. $content,
  433. $visibility,
  434. $lang
  435. );
  436. }
  437. }
  438. if ($add_to_calendar) {
  439. $agenda = new Agenda('admin');
  440. $agenda->addEvent(
  441. $date_start,
  442. $date_end,
  443. false,
  444. $title,
  445. $original_content
  446. );
  447. }
  448. return $resultId;
  449. }
  450. return false;
  451. }
  452. /**
  453. * Makes the announcement id visible only for groups in groups_array.
  454. *
  455. * @param int $announcement_id
  456. * @param array $group_array array of group id
  457. *
  458. * @return bool
  459. */
  460. public static function announcement_for_groups($announcement_id, $group_array)
  461. {
  462. $tbl_announcement_group = Database::get_main_table(
  463. TABLE_MAIN_SYSTEM_ANNOUNCEMENTS_GROUPS
  464. );
  465. //first delete all group associations for this announcement
  466. $res = Database::query(
  467. "DELETE FROM $tbl_announcement_group
  468. WHERE announcement_id=".intval($announcement_id)
  469. );
  470. if ($res === false) {
  471. return false;
  472. }
  473. foreach ($group_array as $group_id) {
  474. if (intval($group_id) != 0) {
  475. $sql = "INSERT INTO $tbl_announcement_group SET
  476. announcement_id=".intval($announcement_id).",
  477. group_id=".intval($group_id);
  478. $res = Database::query($sql);
  479. if ($res === false) {
  480. return false;
  481. }
  482. }
  483. }
  484. return true;
  485. }
  486. /**
  487. * Gets the groups of this announce.
  488. *
  489. * @param int announcement id
  490. *
  491. * @return array array of group id
  492. */
  493. public static function get_announcement_groups($announcement_id)
  494. {
  495. $tbl_announcement_group = Database::get_main_table(TABLE_MAIN_SYSTEM_ANNOUNCEMENTS_GROUPS);
  496. $tbl_group = Database::get_main_table(TABLE_USERGROUP);
  497. //first delete all group associations for this announcement
  498. $sql = "SELECT
  499. g.id as group_id,
  500. g.name as group_name
  501. FROM $tbl_group g , $tbl_announcement_group ag
  502. WHERE
  503. announcement_id =".intval($announcement_id)." AND
  504. ag.group_id = g.id";
  505. $res = Database::query($sql);
  506. $groups = Database::fetch_array($res);
  507. return $groups;
  508. }
  509. /**
  510. * Updates an announcement to the database.
  511. *
  512. * @param int $id of the announcement
  513. * @param string $title title of the announcement
  514. * @param string $content content of the announcement
  515. * @param array $date_start start date (0 => day ; 1 => month ; 2 => year ; 3 => hour ; 4 => minute)
  516. * @param array $date_end end date of (0 => day ; 1 => month ; 2 => year ; 3 => hour ; 4 => minute)
  517. * @param array $visibility
  518. * @param array $lang
  519. * @param int $send_mail
  520. * @param bool $sendEmailTest
  521. *
  522. * @return bool True on success, false on failure
  523. */
  524. public static function update_announcement(
  525. $id,
  526. $title,
  527. $content,
  528. $date_start,
  529. $date_end,
  530. $visibility,
  531. $lang = null,
  532. $send_mail = 0,
  533. $sendEmailTest = false
  534. ) {
  535. $em = Database::getManager();
  536. $announcement = $em->find('ChamiloCoreBundle:SysAnnouncement', $id);
  537. if (!$announcement) {
  538. return false;
  539. }
  540. $a_dateS = explode(' ', $date_start);
  541. $a_arraySD = explode('-', $a_dateS[0]);
  542. $a_arraySH = explode(':', $a_dateS[1]);
  543. $date_start_to_compare = array_merge($a_arraySD, $a_arraySH);
  544. $a_dateE = explode(' ', $date_end);
  545. $a_arrayED = explode('-', $a_dateE[0]);
  546. $a_arrayEH = explode(':', $a_dateE[1]);
  547. $date_end_to_compare = array_merge($a_arrayED, $a_arrayEH);
  548. $lang = is_null($lang) ? '' : $lang;
  549. if (!checkdate($date_start_to_compare[1], $date_start_to_compare[2], $date_start_to_compare[0])) {
  550. echo Display::return_message(get_lang('Invalid start date was given.'));
  551. return false;
  552. }
  553. if (($date_end_to_compare[1] ||
  554. $date_end_to_compare[2] ||
  555. $date_end_to_compare[0]) &&
  556. !checkdate($date_end_to_compare[1], $date_end_to_compare[2], $date_end_to_compare[0])
  557. ) {
  558. echo Display::return_message(get_lang('Invalid end date was given.'));
  559. return false;
  560. }
  561. if (strlen(trim($title)) == 0) {
  562. echo Display::return_message(get_lang('Please enter a title'));
  563. return false;
  564. }
  565. $start = api_get_utc_datetime($date_start);
  566. $end = api_get_utc_datetime($date_end);
  567. //Fixing urls that are sent by email
  568. //$content = str_replace('src=\"/home/', 'src=\"'.api_get_path(WEB_PATH).'home/', $content);
  569. //$content = str_replace('file=/home/', 'file='.api_get_path(WEB_PATH).'home/', $content);
  570. $content = str_replace(
  571. 'src=\"'.api_get_path(REL_HOME_PATH),
  572. 'src=\"'.api_get_path(WEB_PATH).api_get_path(REL_HOME_PATH),
  573. $content
  574. );
  575. $content = str_replace(
  576. 'file='.api_get_path(REL_HOME_PATH),
  577. 'file='.api_get_path(WEB_PATH).api_get_path(REL_HOME_PATH),
  578. $content
  579. );
  580. if ($sendEmailTest) {
  581. self::send_system_announcement_by_email(
  582. $title,
  583. $content,
  584. null,
  585. null,
  586. $lang,
  587. $sendEmailTest
  588. );
  589. } else {
  590. if ($send_mail == 1) {
  591. self::send_system_announcement_by_email(
  592. $title,
  593. $content,
  594. $visibility,
  595. $lang
  596. );
  597. }
  598. }
  599. $dateStart = new DateTime($start, new DateTimeZone('UTC'));
  600. $dateEnd = new DateTime($end, new DateTimeZone('UTC'));
  601. $announcement
  602. ->setLang($lang)
  603. ->setTitle($title)
  604. ->setContent($content)
  605. ->setDateStart($dateStart)
  606. ->setDateEnd($dateEnd)
  607. ->setAccessUrlId(api_get_current_access_url_id());
  608. $em->merge($announcement);
  609. $em->flush();
  610. // Update visibility
  611. $list = self::getVisibilityList();
  612. $table = Database::get_main_table(TABLE_MAIN_SYSTEM_ANNOUNCEMENTS);
  613. foreach ($list as $key => $title) {
  614. $value = isset($visibility[$key]) && $visibility[$key] ? 1 : 0;
  615. $sql = "UPDATE $table SET $key = '$value' WHERE id = $id";
  616. Database::query($sql);
  617. }
  618. return true;
  619. }
  620. /**
  621. * Deletes an announcement.
  622. *
  623. * @param int $id The identifier of the announcement that should be
  624. *
  625. * @return bool True on success, false on failure
  626. */
  627. public static function delete_announcement($id)
  628. {
  629. $table = Database::get_main_table(TABLE_MAIN_SYSTEM_ANNOUNCEMENTS);
  630. $id = intval($id);
  631. $sql = "DELETE FROM $table WHERE id =".$id;
  632. $res = Database::query($sql);
  633. if ($res === false) {
  634. return false;
  635. }
  636. self::deleteAnnouncementPicture($id);
  637. return true;
  638. }
  639. /**
  640. * Gets an announcement.
  641. *
  642. * @param int $id The identifier of the announcement that should be
  643. *
  644. * @return object Object of class StdClass or the required class, containing the query result row
  645. */
  646. public static function get_announcement($id)
  647. {
  648. $table = Database::get_main_table(TABLE_MAIN_SYSTEM_ANNOUNCEMENTS);
  649. $id = intval($id);
  650. $sql = "SELECT * FROM ".$table." WHERE id = ".$id;
  651. $announcement = Database::fetch_object(Database::query($sql));
  652. return $announcement;
  653. }
  654. /**
  655. * Change the visibility of an announcement.
  656. *
  657. * @param int $id
  658. * @param int $user For who should the visibility be changed
  659. * @param bool $visible
  660. *
  661. * @return bool True on success, false on failure
  662. */
  663. public static function set_visibility($id, $user, $visible)
  664. {
  665. $table = Database::get_main_table(TABLE_MAIN_SYSTEM_ANNOUNCEMENTS);
  666. $id = (int) $id;
  667. $list = array_keys(self::getVisibilityList());
  668. $user = trim($user);
  669. $visible = (int) $visible;
  670. if (!in_array($user, $list)) {
  671. return false;
  672. }
  673. $field = $user;
  674. $sql = "UPDATE $table SET ".$field." = '".$visible."'
  675. WHERE id='".$id."'";
  676. $res = Database::query($sql);
  677. if ($res === false) {
  678. return false;
  679. }
  680. return true;
  681. }
  682. /**
  683. * Send a system announcement by e-mail to all teachers/students depending on parameters.
  684. *
  685. * @param string $title
  686. * @param string $content
  687. * @param array $visibility
  688. * @param string $language Language (optional, considered for all languages if left empty)
  689. * @param bool $sendEmailTest
  690. *
  691. * @return bool True if the message was sent or there was no destination matching.
  692. * False on database or e-mail sending error.
  693. */
  694. public static function send_system_announcement_by_email(
  695. $title,
  696. $content,
  697. $visibility,
  698. $language = null,
  699. $sendEmailTest = false
  700. ) {
  701. $content = str_replace(['\r\n', '\n', '\r'], '', $content);
  702. $now = api_get_utc_datetime();
  703. $teacher = $visibility['visible_teacher'];
  704. $student = $visibility['visible_student'];
  705. if ($sendEmailTest) {
  706. MessageManager::send_message_simple(api_get_user_id(), $title, $content);
  707. return true;
  708. }
  709. $urlJoin = '';
  710. $urlCondition = '';
  711. $user_table = Database::get_main_table(TABLE_MAIN_USER);
  712. if (api_is_multiple_url_enabled()) {
  713. $current_access_url_id = api_get_current_access_url_id();
  714. $url_rel_user = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
  715. $urlJoin = " INNER JOIN $url_rel_user uu ON uu.user_id = u.user_id ";
  716. $urlCondition = " AND access_url_id = '".$current_access_url_id."' ";
  717. }
  718. if ($teacher != 0 && $student == 0) {
  719. $sql = "SELECT DISTINCT u.user_id FROM $user_table u $urlJoin
  720. WHERE status = '1' $urlCondition";
  721. }
  722. if ($teacher == 0 && $student != 0) {
  723. $sql = "SELECT DISTINCT u.user_id FROM $user_table u $urlJoin
  724. WHERE status = '5' $urlCondition";
  725. }
  726. if ($teacher != 0 && $student != 0) {
  727. $sql = "SELECT DISTINCT u.user_id FROM $user_table u $urlJoin
  728. WHERE 1 = 1 $urlCondition";
  729. }
  730. if (!isset($sql)) {
  731. return false;
  732. }
  733. if (!empty($language)) {
  734. //special condition because language was already treated for SQL insert before
  735. $sql .= " AND language = '".Database::escape_string($language)."' ";
  736. }
  737. // Sent to active users.
  738. $sql .= " AND email <>'' AND active = 1 ";
  739. // Expiration date
  740. $sql .= " AND (expiration_date = '' OR expiration_date IS NULL OR expiration_date > '$now') ";
  741. if ((empty($teacher) || $teacher == '0') && (empty($student) || $student == '0')) {
  742. return true;
  743. }
  744. $result = Database::query($sql);
  745. if ($result === false) {
  746. return false;
  747. }
  748. $message_sent = false;
  749. while ($row = Database::fetch_array($result, 'ASSOC')) {
  750. MessageManager::send_message_simple($row['user_id'], $title, $content);
  751. $message_sent = true;
  752. }
  753. // Minor validation to clean up the attachment files in the announcement
  754. if (!empty($_FILES)) {
  755. $attachments = $_FILES;
  756. foreach ($attachments as $attachment) {
  757. unlink($attachment['tmp_name']);
  758. }
  759. }
  760. return $message_sent; //true if at least one e-mail was sent
  761. }
  762. /**
  763. * Displays announcements as an slideshow.
  764. *
  765. * @param string $visible see self::VISIBLE_* constants
  766. * @param int $id The identifier of the announcement to display
  767. *
  768. * @return array
  769. */
  770. public static function getAnnouncements($visible, $id = null): array
  771. {
  772. $user_selected_language = Database::escape_string(api_get_interface_language());
  773. $table = Database::get_main_table(TABLE_MAIN_SYSTEM_ANNOUNCEMENTS);
  774. $cut_size = 500;
  775. $now = api_get_utc_datetime();
  776. $sql = "SELECT * FROM $table
  777. WHERE
  778. (lang = '$user_selected_language' OR lang = '') AND
  779. ('$now' >= date_start AND '$now' <= date_end) ";
  780. $sql .= self::getVisibilityCondition($visible);
  781. if (isset($id) && !empty($id)) {
  782. $id = (int) $id;
  783. $sql .= " AND id = $id ";
  784. }
  785. if (api_is_multiple_url_enabled()) {
  786. $current_url_id = api_get_current_access_url_id();
  787. $sql .= " AND access_url_id IN ('1', '$current_url_id') ";
  788. }
  789. $sql .= ' ORDER BY date_start DESC';
  790. $result = Database::query($sql);
  791. $announcements = [];
  792. if (Database::num_rows($result) > 0) {
  793. while ($announcement = Database::fetch_object($result)) {
  794. $announcementData = [
  795. 'id' => $announcement->id,
  796. 'title' => $announcement->title,
  797. 'content' => $announcement->content,
  798. 'picture' => self::getPictureAnnouncement($announcement->id),
  799. 'readMore' => null,
  800. ];
  801. if (empty($id)) {
  802. if (api_strlen(strip_tags($announcement->content)) > $cut_size) {
  803. $announcementData['content'] = cut($announcement->content, $cut_size);
  804. $announcementData['readMore'] = true;
  805. }
  806. }
  807. $announcements[] = $announcementData;
  808. }
  809. }
  810. if (count($announcements) === 0) {
  811. return [];
  812. }
  813. return $announcements;
  814. }
  815. /**
  816. * Get the HTML code for an announcement.
  817. *
  818. * @param int $announcementId The announcement ID
  819. * @param int $visibility The announcement visibility
  820. *
  821. * @return array
  822. */
  823. public static function getAnnouncement($announcementId, $visibility): array
  824. {
  825. $selectedUserLanguage = Database::escape_string(api_get_interface_language());
  826. $announcementTable = Database::get_main_table(TABLE_MAIN_SYSTEM_ANNOUNCEMENTS);
  827. $now = api_get_utc_datetime();
  828. $announcementId = (int) $announcementId;
  829. $whereConditions = [
  830. "(lang = ? OR lang IS NULL OR lang = '') " => $selectedUserLanguage,
  831. "AND (? >= date_start AND ? <= date_end) " => [$now, $now],
  832. "AND id = ? " => $announcementId,
  833. ];
  834. $condition = self::getVisibilityCondition($visibility);
  835. $whereConditions[$condition] = 1;
  836. if (api_is_multiple_url_enabled()) {
  837. $whereConditions["AND access_url_id IN (1, ?) "] = api_get_current_access_url_id();
  838. }
  839. $announcement = Database::select(
  840. '*',
  841. $announcementTable,
  842. [
  843. 'where' => $whereConditions,
  844. 'order' => 'date_start',
  845. ],
  846. 'first'
  847. );
  848. return $announcement;
  849. }
  850. /**
  851. * @return string
  852. */
  853. public static function getCurrentUserVisibility()
  854. {
  855. if (api_is_anonymous()) {
  856. return self::VISIBLE_GUEST;
  857. }
  858. if (api_is_student_boss()) {
  859. return self::VISIBLE_STUDENT_BOSS;
  860. }
  861. if (api_is_session_admin()) {
  862. return self::VISIBLE_SESSION_ADMIN;
  863. }
  864. if (api_is_drh()) {
  865. return self::VISIBLE_DRH;
  866. }
  867. if (api_is_teacher()) {
  868. return self::VISIBLE_TEACHER;
  869. } else {
  870. return self::VISIBLE_STUDENT;
  871. }
  872. }
  873. /**
  874. * Deletes the Announcement picture.
  875. *
  876. * @param int $announcementId
  877. */
  878. public static function deleteAnnouncementPicture($announcementId)
  879. {
  880. $store_path = api_get_path(SYS_UPLOAD_PATH).'announcements';
  881. // image name
  882. $announcementPicture = $store_path.'/announcement_'.$announcementId.'.png';
  883. $announcementPictureSmall = $store_path.'/announcement_'.$announcementId.'_100x100.png';
  884. if (file_exists($announcementPicture)) {
  885. unlink($announcementPicture);
  886. }
  887. if (file_exists($announcementPictureSmall)) {
  888. unlink($announcementPictureSmall);
  889. }
  890. }
  891. /**
  892. * get announcement picture.
  893. *
  894. * @param int $announcementId
  895. *
  896. * @return string|null
  897. */
  898. private static function getPictureAnnouncement($announcementId)
  899. {
  900. $store_path = api_get_path(SYS_UPLOAD_PATH).'announcements';
  901. $announcementPicture = $store_path.'/announcement_'.$announcementId.'.png';
  902. if (file_exists($announcementPicture)) {
  903. $web_path = api_get_path(WEB_UPLOAD_PATH).'announcements';
  904. $urlPicture = $web_path.'/announcement_'.$announcementId.'.png';
  905. return $urlPicture;
  906. }
  907. return null;
  908. }
  909. }