PageRenderTime 43ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/mod/forum/search.php

https://bitbucket.org/kudutest1/moodlegit
PHP | 466 lines | 337 code | 81 blank | 48 comment | 50 complexity | b092c929149f089015233078c91ef5b8 MD5 | raw file
  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. * @package mod-forum
  18. * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
  19. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  20. */
  21. require_once('../../config.php');
  22. require_once('lib.php');
  23. $id = required_param('id', PARAM_INT); // course id
  24. $search = trim(optional_param('search', '', PARAM_NOTAGS)); // search string
  25. $page = optional_param('page', 0, PARAM_INT); // which page to show
  26. $perpage = optional_param('perpage', 10, PARAM_INT); // how many per page
  27. $showform = optional_param('showform', 0, PARAM_INT); // Just show the form
  28. $user = trim(optional_param('user', '', PARAM_NOTAGS)); // Names to search for
  29. $userid = trim(optional_param('userid', 0, PARAM_INT)); // UserID to search for
  30. $forumid = trim(optional_param('forumid', 0, PARAM_INT)); // ForumID to search for
  31. $subject = trim(optional_param('subject', '', PARAM_NOTAGS)); // Subject
  32. $phrase = trim(optional_param('phrase', '', PARAM_NOTAGS)); // Phrase
  33. $words = trim(optional_param('words', '', PARAM_NOTAGS)); // Words
  34. $fullwords = trim(optional_param('fullwords', '', PARAM_NOTAGS)); // Whole words
  35. $notwords = trim(optional_param('notwords', '', PARAM_NOTAGS)); // Words we don't want
  36. $timefromrestrict = optional_param('timefromrestrict', 0, PARAM_INT); // Use starting date
  37. $fromday = optional_param('fromday', 0, PARAM_INT); // Starting date
  38. $frommonth = optional_param('frommonth', 0, PARAM_INT); // Starting date
  39. $fromyear = optional_param('fromyear', 0, PARAM_INT); // Starting date
  40. $fromhour = optional_param('fromhour', 0, PARAM_INT); // Starting date
  41. $fromminute = optional_param('fromminute', 0, PARAM_INT); // Starting date
  42. if ($timefromrestrict) {
  43. $datefrom = make_timestamp($fromyear, $frommonth, $fromday, $fromhour, $fromminute);
  44. } else {
  45. $datefrom = optional_param('datefrom', 0, PARAM_INT); // Starting date
  46. }
  47. $timetorestrict = optional_param('timetorestrict', 0, PARAM_INT); // Use ending date
  48. $today = optional_param('today', 0, PARAM_INT); // Ending date
  49. $tomonth = optional_param('tomonth', 0, PARAM_INT); // Ending date
  50. $toyear = optional_param('toyear', 0, PARAM_INT); // Ending date
  51. $tohour = optional_param('tohour', 0, PARAM_INT); // Ending date
  52. $tominute = optional_param('tominute', 0, PARAM_INT); // Ending date
  53. if ($timetorestrict) {
  54. $dateto = make_timestamp($toyear, $tomonth, $today, $tohour, $tominute);
  55. } else {
  56. $dateto = optional_param('dateto', 0, PARAM_INT); // Ending date
  57. }
  58. $PAGE->set_pagelayout('standard');
  59. $PAGE->set_url($FULLME); //TODO: this is very sloppy --skodak
  60. if (empty($search)) { // Check the other parameters instead
  61. if (!empty($words)) {
  62. $search .= ' '.$words;
  63. }
  64. if (!empty($userid)) {
  65. $search .= ' userid:'.$userid;
  66. }
  67. if (!empty($forumid)) {
  68. $search .= ' forumid:'.$forumid;
  69. }
  70. if (!empty($user)) {
  71. $search .= ' '.forum_clean_search_terms($user, 'user:');
  72. }
  73. if (!empty($subject)) {
  74. $search .= ' '.forum_clean_search_terms($subject, 'subject:');
  75. }
  76. if (!empty($fullwords)) {
  77. $search .= ' '.forum_clean_search_terms($fullwords, '+');
  78. }
  79. if (!empty($notwords)) {
  80. $search .= ' '.forum_clean_search_terms($notwords, '-');
  81. }
  82. if (!empty($phrase)) {
  83. $search .= ' "'.$phrase.'"';
  84. }
  85. if (!empty($datefrom)) {
  86. $search .= ' datefrom:'.$datefrom;
  87. }
  88. if (!empty($dateto)) {
  89. $search .= ' dateto:'.$dateto;
  90. }
  91. $individualparams = true;
  92. } else {
  93. $individualparams = false;
  94. }
  95. if ($search) {
  96. $search = forum_clean_search_terms($search);
  97. }
  98. if (!$course = $DB->get_record('course', array('id'=>$id))) {
  99. print_error('invalidcourseid');
  100. }
  101. require_course_login($course);
  102. add_to_log($course->id, "forum", "search", "search.php?id=$course->id&amp;search=".urlencode($search), $search);
  103. $strforums = get_string("modulenameplural", "forum");
  104. $strsearch = get_string("search", "forum");
  105. $strsearchresults = get_string("searchresults", "forum");
  106. $strpage = get_string("page");
  107. if (!$search || $showform) {
  108. $PAGE->navbar->add($strforums, new moodle_url('/mod/forum/index.php', array('id'=>$course->id)));
  109. $PAGE->navbar->add(get_string('advancedsearch', 'forum'));
  110. $PAGE->set_title($strsearch);
  111. $PAGE->set_heading($course->fullname);
  112. echo $OUTPUT->header();
  113. forum_print_big_search_form($course);
  114. echo $OUTPUT->footer();
  115. exit;
  116. }
  117. /// We need to do a search now and print results
  118. $searchterms = str_replace('forumid:', 'instance:', $search);
  119. $searchterms = explode(' ', $searchterms);
  120. $searchform = forum_search_form($course, $search);
  121. $PAGE->navbar->add($strsearch, new moodle_url('/mod/forum/search.php', array('id'=>$course->id)));
  122. $PAGE->navbar->add($strsearchresults);
  123. if (!$posts = forum_search_posts($searchterms, $course->id, $page*$perpage, $perpage, $totalcount)) {
  124. $PAGE->set_title($strsearchresults);
  125. $PAGE->set_heading($course->fullname);
  126. echo $OUTPUT->header();
  127. echo $OUTPUT->heading(get_string("noposts", "forum"));
  128. if (!$individualparams) {
  129. $words = $search;
  130. }
  131. forum_print_big_search_form($course);
  132. echo $OUTPUT->footer();
  133. exit;
  134. }
  135. //including this here to prevent it being included if there are no search results
  136. require_once($CFG->dirroot.'/rating/lib.php');
  137. //set up the ratings information that will be the same for all posts
  138. $ratingoptions = new stdClass();
  139. $ratingoptions->component = 'mod_forum';
  140. $ratingoptions->ratingarea = 'post';
  141. $ratingoptions->userid = $USER->id;
  142. $ratingoptions->returnurl = $PAGE->url->out(false);
  143. $rm = new rating_manager();
  144. $PAGE->set_title($strsearchresults);
  145. $PAGE->set_heading($course->fullname);
  146. $PAGE->set_button($searchform);
  147. echo $OUTPUT->header();
  148. echo '<div class="reportlink">';
  149. echo '<a href="search.php?id='.$course->id.
  150. '&amp;user='.urlencode($user).
  151. '&amp;userid='.$userid.
  152. '&amp;forumid='.$forumid.
  153. '&amp;subject='.urlencode($subject).
  154. '&amp;phrase='.urlencode($phrase).
  155. '&amp;words='.urlencode($words).
  156. '&amp;fullwords='.urlencode($fullwords).
  157. '&amp;notwords='.urlencode($notwords).
  158. '&amp;dateto='.$dateto.
  159. '&amp;datefrom='.$datefrom.
  160. '&amp;showform=1'.
  161. '">'.get_string('advancedsearch','forum').'...</a>';
  162. echo '</div>';
  163. echo $OUTPUT->heading("$strsearchresults: $totalcount");
  164. $url = new moodle_url('search.php', array('search' => $search, 'id' => $course->id, 'perpage' => $perpage));
  165. echo $OUTPUT->paging_bar($totalcount, $page, $perpage, $url);
  166. //added to implement highlighting of search terms found only in HTML markup
  167. //fiedorow - 9/2/2005
  168. $strippedsearch = str_replace('user:','',$search);
  169. $strippedsearch = str_replace('subject:','',$strippedsearch);
  170. $strippedsearch = str_replace('&quot;','',$strippedsearch);
  171. $searchterms = explode(' ', $strippedsearch); // Search for words independently
  172. foreach ($searchterms as $key => $searchterm) {
  173. if (preg_match('/^\-/',$searchterm)) {
  174. unset($searchterms[$key]);
  175. } else {
  176. $searchterms[$key] = preg_replace('/^\+/','',$searchterm);
  177. }
  178. }
  179. $strippedsearch = implode(' ', $searchterms); // Rebuild the string
  180. foreach ($posts as $post) {
  181. // Replace the simple subject with the three items forum name -> thread name -> subject
  182. // (if all three are appropriate) each as a link.
  183. if (! $discussion = $DB->get_record('forum_discussions', array('id' => $post->discussion))) {
  184. print_error('invaliddiscussionid', 'forum');
  185. }
  186. if (! $forum = $DB->get_record('forum', array('id' => "$discussion->forum"))) {
  187. print_error('invalidforumid', 'forum');
  188. }
  189. if (!$cm = get_coursemodule_from_instance('forum', $forum->id)) {
  190. print_error('invalidcoursemodule');
  191. }
  192. $post->subject = highlight($strippedsearch, $post->subject);
  193. $discussion->name = highlight($strippedsearch, $discussion->name);
  194. $fullsubject = "<a href=\"view.php?f=$forum->id\">".format_string($forum->name,true)."</a>";
  195. if ($forum->type != 'single') {
  196. $fullsubject .= " -> <a href=\"discuss.php?d=$discussion->id\">".format_string($discussion->name,true)."</a>";
  197. if ($post->parent != 0) {
  198. $fullsubject .= " -> <a href=\"discuss.php?d=$post->discussion&amp;parent=$post->id\">".format_string($post->subject,true)."</a>";
  199. }
  200. }
  201. $post->subject = $fullsubject;
  202. $post->subjectnoformat = true;
  203. //add the ratings information to the post
  204. //Unfortunately seem to have do this individually as posts may be from different forums
  205. if ($forum->assessed != RATING_AGGREGATE_NONE) {
  206. $modcontext = context_module::instance($cm->id);
  207. $ratingoptions->context = $modcontext;
  208. $ratingoptions->items = array($post);
  209. $ratingoptions->aggregate = $forum->assessed;//the aggregation method
  210. $ratingoptions->scaleid = $forum->scale;
  211. $ratingoptions->assesstimestart = $forum->assesstimestart;
  212. $ratingoptions->assesstimefinish = $forum->assesstimefinish;
  213. $postswithratings = $rm->get_ratings($ratingoptions);
  214. if ($postswithratings && count($postswithratings)==1) {
  215. $post = $postswithratings[0];
  216. }
  217. }
  218. // Identify search terms only found in HTML markup, and add a warning about them to
  219. // the start of the message text. However, do not do the highlighting here. forum_print_post
  220. // will do it for us later.
  221. $missing_terms = "";
  222. $options = new stdClass();
  223. $options->trusted = $post->messagetrust;
  224. $post->message = highlight($strippedsearch,
  225. format_text($post->message, $post->messageformat, $options, $course->id),
  226. 0, '<fgw9sdpq4>', '</fgw9sdpq4>');
  227. foreach ($searchterms as $searchterm) {
  228. if (preg_match("/$searchterm/i",$post->message) && !preg_match('/<fgw9sdpq4>'.$searchterm.'<\/fgw9sdpq4>/i',$post->message)) {
  229. $missing_terms .= " $searchterm";
  230. }
  231. }
  232. $post->message = str_replace('<fgw9sdpq4>', '<span class="highlight">', $post->message);
  233. $post->message = str_replace('</fgw9sdpq4>', '</span>', $post->message);
  234. if ($missing_terms) {
  235. $strmissingsearchterms = get_string('missingsearchterms','forum');
  236. $post->message = '<p class="highlight2">'.$strmissingsearchterms.' '.$missing_terms.'</p>'.$post->message;
  237. }
  238. // Prepare a link to the post in context, to be displayed after the forum post.
  239. $fulllink = "<a href=\"discuss.php?d=$post->discussion#p$post->id\">".get_string("postincontext", "forum")."</a>";
  240. // Now pring the post.
  241. forum_print_post($post, $discussion, $forum, $cm, $course, false, false, false,
  242. $fulllink, '', -99, false);
  243. }
  244. echo $OUTPUT->paging_bar($totalcount, $page, $perpage, $url);
  245. echo $OUTPUT->footer();
  246. /**
  247. * @todo Document this function
  248. */
  249. function forum_print_big_search_form($course) {
  250. global $CFG, $DB, $words, $subject, $phrase, $user, $userid, $fullwords, $notwords, $datefrom, $dateto, $PAGE, $OUTPUT;
  251. echo $OUTPUT->box(get_string('searchforumintro', 'forum'), 'searchbox boxaligncenter', 'intro');
  252. echo $OUTPUT->box_start('generalbox boxaligncenter');
  253. echo html_writer::script('', $CFG->wwwroot.'/mod/forum/forum.js');
  254. echo '<form id="searchform" action="search.php" method="get">';
  255. echo '<table cellpadding="10" class="searchbox" id="form">';
  256. echo '<tr>';
  257. echo '<td class="c0"><label for="words">'.get_string('searchwords', 'forum').'</label>';
  258. echo '<input type="hidden" value="'.$course->id.'" name="id" alt="" /></td>';
  259. echo '<td class="c1"><input type="text" size="35" name="words" id="words"value="'.s($words, true).'" alt="" /></td>';
  260. echo '</tr>';
  261. echo '<tr>';
  262. echo '<td class="c0"><label for="phrase">'.get_string('searchphrase', 'forum').'</label></td>';
  263. echo '<td class="c1"><input type="text" size="35" name="phrase" id="phrase" value="'.s($phrase, true).'" alt="" /></td>';
  264. echo '</tr>';
  265. echo '<tr>';
  266. echo '<td class="c0"><label for="notwords">'.get_string('searchnotwords', 'forum').'</label></td>';
  267. echo '<td class="c1"><input type="text" size="35" name="notwords" id="notwords" value="'.s($notwords, true).'" alt="" /></td>';
  268. echo '</tr>';
  269. if ($DB->get_dbfamily() == 'mysql' || $DB->get_dbfamily() == 'postgres') {
  270. echo '<tr>';
  271. echo '<td class="c0"><label for="fullwords">'.get_string('searchfullwords', 'forum').'</label></td>';
  272. echo '<td class="c1"><input type="text" size="35" name="fullwords" id="fullwords" value="'.s($fullwords, true).'" alt="" /></td>';
  273. echo '</tr>';
  274. }
  275. echo '<tr>';
  276. echo '<td class="c0">'.get_string('searchdatefrom', 'forum').'</td>';
  277. echo '<td class="c1">';
  278. if (empty($datefrom)) {
  279. $datefromchecked = '';
  280. $datefrom = make_timestamp(2000, 1, 1, 0, 0, 0);
  281. }else{
  282. $datefromchecked = 'checked="checked"';
  283. }
  284. echo '<input name="timefromrestrict" type="checkbox" value="1" alt="'.get_string('searchdatefrom', 'forum').'" onclick="return lockoptions(\'searchform\', \'timefromrestrict\', timefromitems)" '. $datefromchecked . ' /> ';
  285. $selectors = html_writer::select_time('days', 'fromday', $datefrom)
  286. . html_writer::select_time('months', 'frommonth', $datefrom)
  287. . html_writer::select_time('years', 'fromyear', $datefrom)
  288. . html_writer::select_time('hours', 'fromhour', $datefrom)
  289. . html_writer::select_time('minutes', 'fromminute', $datefrom);
  290. echo $selectors;
  291. echo '<input type="hidden" name="hfromday" value="0" />';
  292. echo '<input type="hidden" name="hfrommonth" value="0" />';
  293. echo '<input type="hidden" name="hfromyear" value="0" />';
  294. echo '<input type="hidden" name="hfromhour" value="0" />';
  295. echo '<input type="hidden" name="hfromminute" value="0" />';
  296. echo '</td>';
  297. echo '</tr>';
  298. echo '<tr>';
  299. echo '<td class="c0">'.get_string('searchdateto', 'forum').'</td>';
  300. echo '<td class="c1">';
  301. if (empty($dateto)) {
  302. $datetochecked = '';
  303. $dateto = time()+3600;
  304. }else{
  305. $datetochecked = 'checked="checked"';
  306. }
  307. echo '<input name="timetorestrict" type="checkbox" value="1" alt="'.get_string('searchdateto', 'forum').'" onclick="return lockoptions(\'searchform\', \'timetorestrict\', timetoitems)" ' .$datetochecked. ' /> ';
  308. $selectors = html_writer::select_time('days', 'today', $dateto)
  309. . html_writer::select_time('months', 'tomonth', $dateto)
  310. . html_writer::select_time('years', 'toyear', $dateto)
  311. . html_writer::select_time('hours', 'tohour', $dateto)
  312. . html_writer::select_time('minutes', 'tominute', $dateto);
  313. echo $selectors;
  314. echo '<input type="hidden" name="htoday" value="0" />';
  315. echo '<input type="hidden" name="htomonth" value="0" />';
  316. echo '<input type="hidden" name="htoyear" value="0" />';
  317. echo '<input type="hidden" name="htohour" value="0" />';
  318. echo '<input type="hidden" name="htominute" value="0" />';
  319. echo '</td>';
  320. echo '</tr>';
  321. echo '<tr>';
  322. echo '<td class="c0"><label for="menuforumid">'.get_string('searchwhichforums', 'forum').'</label></td>';
  323. echo '<td class="c1">';
  324. echo html_writer::select(forum_menu_list($course), 'forumid', '', array(''=>get_string('allforums', 'forum')));
  325. echo '</td>';
  326. echo '</tr>';
  327. echo '<tr>';
  328. echo '<td class="c0"><label for="subject">'.get_string('searchsubject', 'forum').'</label></td>';
  329. echo '<td class="c1"><input type="text" size="35" name="subject" id="subject" value="'.s($subject, true).'" alt="" /></td>';
  330. echo '</tr>';
  331. echo '<tr>';
  332. echo '<td class="c0"><label for="user">'.get_string('searchuser', 'forum').'</label></td>';
  333. echo '<td class="c1"><input type="text" size="35" name="user" id="user" value="'.s($user, true).'" alt="" /></td>';
  334. echo '</tr>';
  335. echo '<tr>';
  336. echo '<td class="submit" colspan="2" align="center">';
  337. echo '<input type="submit" value="'.get_string('searchforums', 'forum').'" alt="" /></td>';
  338. echo '</tr>';
  339. echo '</table>';
  340. echo '</form>';
  341. echo html_writer::script(js_writer::function_call('lockoptions_timetoitems'));
  342. echo html_writer::script(js_writer::function_call('lockoptions_timefromitems'));
  343. echo $OUTPUT->box_end();
  344. }
  345. /**
  346. * This function takes each word out of the search string, makes sure they are at least
  347. * two characters long and returns an array containing every good word.
  348. *
  349. * @param string $words String containing space-separated strings to search for
  350. * @param string $prefix String to prepend to the each token taken out of $words
  351. * @returns array
  352. * @todo Take the hardcoded limit out of this function and put it into a user-specified parameter
  353. */
  354. function forum_clean_search_terms($words, $prefix='') {
  355. $searchterms = explode(' ', $words);
  356. foreach ($searchterms as $key => $searchterm) {
  357. if (strlen($searchterm) < 2) {
  358. unset($searchterms[$key]);
  359. } else if ($prefix) {
  360. $searchterms[$key] = $prefix.$searchterm;
  361. }
  362. }
  363. return trim(implode(' ', $searchterms));
  364. }
  365. /**
  366. * @todo Document this function
  367. */
  368. function forum_menu_list($course) {
  369. $menu = array();
  370. $modinfo = get_fast_modinfo($course);
  371. if (empty($modinfo->instances['forum'])) {
  372. return $menu;
  373. }
  374. foreach ($modinfo->instances['forum'] as $cm) {
  375. if (!$cm->uservisible) {
  376. continue;
  377. }
  378. $context = context_module::instance($cm->id);
  379. if (!has_capability('mod/forum:viewdiscussion', $context)) {
  380. continue;
  381. }
  382. $menu[$cm->instance] = format_string($cm->name);
  383. }
  384. return $menu;
  385. }