index.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. <?php
  2. // This file is part of Moodle - http://moodle.org/
  3. //
  4. // Moodle is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // Moodle is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
  16. /**
  17. * A page displaying the user's contacts and messages
  18. *
  19. * @package core_message
  20. * @copyright 2010 Andrew Davis
  21. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  22. */
  23. require_once('../config.php');
  24. require_once('lib.php');
  25. require_once('send_form.php');
  26. require_login(0, false);
  27. if (isguestuser()) {
  28. redirect($CFG->wwwroot);
  29. }
  30. if (empty($CFG->messaging)) {
  31. print_error('disabled', 'message');
  32. }
  33. //'viewing' is the preferred URL parameter but we'll still accept usergroup in case its referenced externally
  34. $usergroup = optional_param('usergroup', MESSAGE_VIEW_UNREAD_MESSAGES, PARAM_ALPHANUMEXT);
  35. $viewing = optional_param('viewing', $usergroup, PARAM_ALPHANUMEXT);
  36. $history = optional_param('history', MESSAGE_HISTORY_SHORT, PARAM_INT);
  37. $search = optional_param('search', '', PARAM_CLEAN); //TODO: use PARAM_RAW, but make sure we use s() and p() properly
  38. //the same param as 1.9 and the param we have been logging. Use this parameter.
  39. $user1id = optional_param('user1', $USER->id, PARAM_INT);
  40. //2.0 shipped using this param. Retaining it only for compatibility. It should be removed.
  41. $user1id = optional_param('user', $user1id, PARAM_INT);
  42. //the same param as 1.9 and the param we have been logging. Use this parameter.
  43. $user2id = optional_param('user2', 0, PARAM_INT);
  44. //The class send_form supplies the receiving user id as 'id'
  45. $user2id = optional_param('id', $user2id, PARAM_INT);
  46. $addcontact = optional_param('addcontact', 0, PARAM_INT); // adding a contact
  47. $removecontact = optional_param('removecontact', 0, PARAM_INT); // removing a contact
  48. $blockcontact = optional_param('blockcontact', 0, PARAM_INT); // blocking a contact
  49. $unblockcontact = optional_param('unblockcontact', 0, PARAM_INT); // unblocking a contact
  50. $deletemessageid = optional_param('deletemessageid', 0, PARAM_INT);
  51. $deletemessageconfirm = optional_param('deletemessageconfirm', 0, PARAM_BOOL);
  52. if ($deletemessageid) {
  53. $deletemessagetype = required_param('deletemessagetype', PARAM_ALPHAEXT);
  54. }
  55. //for search
  56. $advancedsearch = optional_param('advanced', 0, PARAM_INT);
  57. //if they have numerous contacts or are viewing course participants we might need to page through them
  58. $page = optional_param('page', 0, PARAM_INT);
  59. $url = new moodle_url('/message/index.php', array('user1' => $user1id));
  60. if ($user2id !== 0) {
  61. $url->param('user2', $user2id);
  62. //Switch view back to contacts if:
  63. //1) theyve searched and selected a user
  64. //2) they've viewed recent messages or notifications and clicked through to a user
  65. if ($viewing == MESSAGE_VIEW_SEARCH || $viewing == MESSAGE_VIEW_RECENT_NOTIFICATIONS) {
  66. $viewing = MESSAGE_VIEW_CONTACTS;
  67. }
  68. }
  69. if ($viewing != MESSAGE_VIEW_UNREAD_MESSAGES) {
  70. $url->param('viewing', $viewing);
  71. }
  72. $PAGE->set_url($url);
  73. // Disable message notification popups while the user is viewing their messages
  74. $PAGE->set_popup_notification_allowed(false);
  75. $user1 = null;
  76. $currentuser = true;
  77. $showactionlinks = true;
  78. if ($user1id != $USER->id) {
  79. $user1 = $DB->get_record('user', array('id' => $user1id));
  80. if (!$user1) {
  81. print_error('invaliduserid');
  82. }
  83. $currentuser = false;//if we're looking at someone else's messages we need to lock/remove some UI elements
  84. $showactionlinks = false;
  85. } else {
  86. $user1 = $USER;
  87. }
  88. unset($user1id);
  89. $user2 = null;
  90. if (!empty($user2id)) {
  91. $user2 = core_user::get_user($user2id);
  92. if (!$user2) {
  93. print_error('invaliduserid');
  94. }
  95. }
  96. unset($user2id);
  97. $user2realuser = !empty($user2) && core_user::is_real_user($user2->id);
  98. $showactionlinks = $showactionlinks && $user2realuser;
  99. $systemcontext = context_system::instance();
  100. if ($currentuser === false && !has_capability('moodle/site:readallmessages', $systemcontext)) {
  101. print_error('accessdenied','admin');
  102. }
  103. if (substr($viewing, 0, 7) == MESSAGE_VIEW_COURSE) {
  104. $courseid = intval(substr($viewing, 7));
  105. require_login($courseid);
  106. require_capability('moodle/course:viewparticipants', context_course::instance($courseid));
  107. $PAGE->set_pagelayout('incourse');
  108. } else {
  109. $PAGE->set_pagelayout('standard');
  110. }
  111. // Page context should always be set to user.
  112. $PAGE->set_context(context_user::instance($user1->id));
  113. if (!empty($user1->id) && $user1->id != $USER->id) {
  114. $PAGE->navigation->extend_for_user($user1);
  115. }
  116. if (!empty($user2->id) && $user2realuser && ($user2->id != $USER->id)) {
  117. $PAGE->navigation->extend_for_user($user2);
  118. }
  119. $strmessages = get_string('messages', 'message');
  120. if ($user2realuser) {
  121. $user2fullname = fullname($user2);
  122. $PAGE->set_title("$strmessages: $user2fullname");
  123. $PAGE->set_heading("$strmessages: $user2fullname");
  124. } else {
  125. $PAGE->set_title("{$SITE->shortname}: $strmessages");
  126. $PAGE->set_heading("{$SITE->shortname}: $strmessages");
  127. }
  128. /// Process any contact maintenance requests there may be
  129. if ($addcontact and confirm_sesskey()) {
  130. message_add_contact($addcontact);
  131. redirect($CFG->wwwroot . '/message/index.php?viewing=contacts&id='.$addcontact);
  132. }
  133. if ($removecontact and confirm_sesskey()) {
  134. message_remove_contact($removecontact);
  135. }
  136. if ($blockcontact and confirm_sesskey()) {
  137. message_block_contact($blockcontact);
  138. }
  139. if ($unblockcontact and confirm_sesskey()) {
  140. message_unblock_contact($unblockcontact);
  141. }
  142. if ($deletemessageid and confirm_sesskey()) {
  143. // Check that the message actually exists.
  144. if ($message = $DB->get_record($deletemessagetype, array('id' => $deletemessageid))) {
  145. // Check that we are allowed to delete this message.
  146. if (message_can_delete_message($message, $user1->id)) {
  147. if (!$deletemessageconfirm) {
  148. $confirmurl = new moodle_url('/message/index.php', array('user1' => $user1->id, 'user2' => $user2->id,
  149. 'viewing' => $viewing, 'deletemessageid' => $message->id, 'deletemessagetype' => $deletemessagetype,
  150. 'deletemessageconfirm' => 1, 'sesskey' => sesskey()));
  151. $confirmbutton = new single_button($confirmurl, get_string('delete'), 'post');
  152. $strdeletemessage = get_string('deletemessage', 'message');
  153. $PAGE->set_title($strdeletemessage);
  154. echo $OUTPUT->header();
  155. echo $OUTPUT->heading($strdeletemessage);
  156. echo $OUTPUT->confirm(get_string('deletemessageconfirmation', 'message'), $confirmbutton, $url);
  157. echo $OUTPUT->footer();
  158. exit();
  159. }
  160. message_delete_message($message, $user1->id);
  161. }
  162. }
  163. redirect($url);
  164. }
  165. //was a message sent? Do NOT allow someone looking at someone else's messages to send them.
  166. $messageerror = null;
  167. if ($currentuser && !empty($user2) && has_capability('moodle/site:sendmessage', $systemcontext)) {
  168. // Check that the user is not blocking us!!
  169. if (message_is_user_blocked($user2, $user1)) {
  170. $messageerror = get_string('userisblockingyou', 'message');
  171. }
  172. // Check that we're not non-contact block by the user.
  173. if (message_is_user_non_contact_blocked($user2, $user1)) {
  174. $messageerror = get_string('userisblockingyounoncontact', 'message', fullname($user2));
  175. }
  176. if (empty($messageerror)) {
  177. $mform = new send_form();
  178. $defaultmessage = new stdClass;
  179. $defaultmessage->id = $user2->id;
  180. $defaultmessage->viewing = $viewing;
  181. $defaultmessage->message = '';
  182. //Check if the current user has sent a message
  183. $data = $mform->get_data();
  184. if (!empty($data) && !empty($data->message)) {
  185. if (!confirm_sesskey()) {
  186. print_error('invalidsesskey');
  187. }
  188. $messageid = message_post_message($user1, $user2, $data->message, FORMAT_MOODLE);
  189. if (!empty($messageid)) {
  190. //including the id of the user sending the message in the logged URL so the URL works for admins
  191. //note message ID may be misleading as the message may potentially get a different ID when moved from message to message_read
  192. redirect($CFG->wwwroot . '/message/index.php?viewing='.$viewing.'&id='.$user2->id);
  193. }
  194. }
  195. }
  196. }
  197. $strmessages = get_string('messages', 'message');
  198. if ($user2realuser) {
  199. $user2fullname = fullname($user2);
  200. $PAGE->set_title("$strmessages: $user2fullname");
  201. } else {
  202. $PAGE->set_title("{$SITE->shortname}: $strmessages");
  203. }
  204. $PAGE->set_heading(fullname($user1));
  205. // Remove the user node from the main navigation for this page.
  206. $usernode = $PAGE->navigation->find('users', null);
  207. $usernode->remove();
  208. $settings = $PAGE->settingsnav->find('messages', null);
  209. // Add the user we are contacting to the breadcrumb.
  210. if (!empty($user2realuser)) {
  211. $usernode = $settings->add(fullname($user2), $url);
  212. $usernode->make_active();
  213. } else {
  214. $settings->make_active();
  215. }
  216. //now the page contents
  217. echo $OUTPUT->header();
  218. echo $OUTPUT->box_start('message');
  219. $countunread = 0; //count of unread messages from $user2
  220. $countunreadtotal = 0; //count of unread messages from all users
  221. //we're dealing with unread messages early so the contact list will accurately reflect what is read/unread
  222. $viewingnewmessages = false;
  223. if (!empty($user2)) {
  224. //are there any unread messages from $user2
  225. $countunread = message_count_unread_messages($user1, $user2);
  226. if ($countunread>0) {
  227. //mark the messages we're going to display as read
  228. message_mark_messages_read($user1->id, $user2->id);
  229. if($viewing == MESSAGE_VIEW_UNREAD_MESSAGES) {
  230. $viewingnewmessages = true;
  231. }
  232. }
  233. }
  234. $countunreadtotal = message_count_unread_messages($user1);
  235. if ($currentuser && $countunreadtotal == 0 && $viewing == MESSAGE_VIEW_UNREAD_MESSAGES && empty($user2)) {
  236. // If the user has no unread messages, show the search box.
  237. // We don't do this when a user is viewing another user's messages as search doesn't
  238. // handle user A searching user B's messages properly.
  239. $viewing = MESSAGE_VIEW_SEARCH;
  240. }
  241. $blockedusers = message_get_blocked_users($user1, $user2);
  242. $countblocked = count($blockedusers);
  243. list($onlinecontacts, $offlinecontacts, $strangers) = message_get_contacts($user1, $user2);
  244. message_print_contact_selector($countunreadtotal, $viewing, $user1, $user2, $blockedusers, $onlinecontacts, $offlinecontacts, $strangers, $showactionlinks, $page);
  245. echo html_writer::start_tag('div', array('class' => 'messagearea mdl-align'));
  246. if (!empty($user2)) {
  247. echo html_writer::start_tag('div', array('class' => 'mdl-left messagehistory'));
  248. $visible = 'visible';
  249. $hidden = 'hiddenelement'; //cant just use hidden as mform adds that class to its fieldset for something else
  250. $recentlinkclass = $recentlabelclass = $historylinkclass = $historylabelclass = $visible;
  251. if ($history == MESSAGE_HISTORY_ALL) {
  252. $displaycount = 0;
  253. $recentlabelclass = $historylinkclass = $hidden;
  254. } else if($viewingnewmessages) {
  255. //if user is viewing new messages only show them the new messages
  256. $displaycount = $countunread;
  257. $recentlabelclass = $historylabelclass = $hidden;
  258. } else {
  259. //default to only showing the last few messages
  260. $displaycount = MESSAGE_SHORTVIEW_LIMIT;
  261. if ($countunread>MESSAGE_SHORTVIEW_LIMIT) {
  262. $displaycount = $countunread;
  263. }
  264. $recentlinkclass = $historylabelclass = $hidden;
  265. }
  266. $messagehistorylink = html_writer::start_tag('div', array('class' => 'mdl-align messagehistorytype'));
  267. $messagehistorylink .= html_writer::link($PAGE->url->out(false).'&history='.MESSAGE_HISTORY_ALL,
  268. get_string('messagehistoryfull','message'),
  269. array('class' => $historylinkclass));
  270. $messagehistorylink .= html_writer::start_tag('span', array('class' => $historylabelclass));
  271. $messagehistorylink .= get_string('messagehistoryfull','message');
  272. $messagehistorylink .= html_writer::end_tag('span');
  273. $messagehistorylink .= '&nbsp;|&nbsp;'.html_writer::link($PAGE->url->out(false).'&history='.MESSAGE_HISTORY_SHORT,
  274. get_string('mostrecent','message'),
  275. array('class' => $recentlinkclass));
  276. $messagehistorylink .= html_writer::start_tag('span', array('class' => $recentlabelclass));
  277. $messagehistorylink .= get_string('mostrecent','message');
  278. $messagehistorylink .= html_writer::end_tag('span');
  279. if ($viewingnewmessages) {
  280. $messagehistorylink .= '&nbsp;|&nbsp;'.html_writer::start_tag('span');//, array('class' => $historyclass)
  281. $messagehistorylink .= get_string('unreadnewmessages','message',$displaycount);
  282. $messagehistorylink .= html_writer::end_tag('span');
  283. }
  284. $messagehistorylink .= html_writer::end_tag('div');
  285. message_print_message_history($user1, $user2, $search, $displaycount, $messagehistorylink, $viewingnewmessages, $showactionlinks);
  286. echo html_writer::end_tag('div');
  287. //send message form
  288. if ($currentuser && has_capability('moodle/site:sendmessage', $systemcontext) && $user2realuser) {
  289. echo html_writer::start_tag('div', array('class' => 'mdl-align messagesend'));
  290. if (!empty($messageerror)) {
  291. echo html_writer::tag('span', $messageerror, array('id' => 'messagewarning'));
  292. } else {
  293. // Display a warning if the current user is blocking non-contacts and is about to message to a non-contact
  294. // Otherwise they may wonder why they never get a reply
  295. if (message_is_user_non_contact_blocked($user1, $user2)) {
  296. $msg = get_string('messagingblockednoncontact', 'message', fullname($user2));
  297. echo html_writer::tag('span', $msg, array('id' => 'messagewarning'));
  298. }
  299. $mform = new send_form();
  300. $defaultmessage = new stdClass;
  301. $defaultmessage->id = $user2->id;
  302. $defaultmessage->viewing = $viewing;
  303. $defaultmessage->message = '';
  304. //$defaultmessage->messageformat = FORMAT_MOODLE;
  305. $mform->set_data($defaultmessage);
  306. $mform->display();
  307. }
  308. echo html_writer::end_tag('div');
  309. }
  310. } else if ($viewing == MESSAGE_VIEW_SEARCH) {
  311. message_print_search($advancedsearch, $user1);
  312. } else if ($viewing == MESSAGE_VIEW_RECENT_CONVERSATIONS) {
  313. message_print_recent_conversations($user1, false, $showactionlinks);
  314. } else if ($viewing == MESSAGE_VIEW_RECENT_NOTIFICATIONS) {
  315. message_print_recent_notifications($user1);
  316. }
  317. echo html_writer::end_tag('div');
  318. echo $OUTPUT->box_end();
  319. echo $OUTPUT->footer();