function annotation_summary_query($a) { $this->moodlemia = moodle_marginalia::get_instance(); if ($a) { $this->from_params($a); } }
function moodle_keyword_service($userid) { global $CFG; $moodlemia = moodle_marginalia::get_instance(); KeywordService::KeywordService($moodlemia->get_host(), $moodlemia->get_keyword_service_path(), $userid, $CFG->wwwroot); $this->tablePrefix = $CFG->prefix; }
public static function get_instance() { if (!moodle_marginalia::$singleton) { moodle_marginalia::$singleton = new moodle_marginalia(); } return moodle_marginalia::$singleton; }
if (!empty($parent) && !forum_user_can_see_post($forum, $discussion, $post, null, $cm)) { print_error('cannotreply', 'forum'); } if (empty($parent) && empty($edit) && !forum_user_can_post_discussion($forum, $groupid, -1, $cm, $modcontext)) { print_error('cannotcreatediscussion', 'forum'); } if ($forum->type == 'qanda' && !has_capability('mod/forum:viewqandawithoutposting', $modcontext) && !empty($discussion->id) && !forum_user_has_posted($forum->id, $discussion->id, $USER->id)) { echo $OUTPUT->notification(get_string('qandanotify', 'forum')); } forum_check_throttling($forum, $cm); if (!empty($parent)) { if (!($discussion = $DB->get_record('forum_discussions', array('id' => $parent->discussion)))) { print_error('notpartofdiscussion', 'forum'); } // #marginalia begin $moodlemia = moodle_marginalia::get_instance(); $miaprofile = $moodlemia->get_profile($PAGE->url->out(false)); if ($miaprofile) { $miaprofile->emit_body(); $miaprofile->emit_margin_controls(); } // #marginalia end forum_print_post($parent, $discussion, $forum, $cm, $course, false, false, false); if (empty($post->edit)) { if ($forum->type != 'qanda' || forum_user_can_see_discussion($forum, $discussion, $modcontext)) { $forumtracked = forum_tp_is_tracked($forum); $posts = forum_get_all_discussion_posts($discussion->id, "created ASC", $forumtracked); forum_print_posts_threaded($course, $cm, $forum, $discussion, $parent, 0, false, $forumtracked, $posts); } } } else {
function show_html($annotations, $annotation_count) { global $CFG, $USER, $PAGE, $OUTPUT, $DB; $PAGE->set_url($this->summary->summary_url()); $blockpath = '/blocks/marginalia'; // was ANNOTATION_PATH $PAGE->requires->css($blockpath . '/summary-styles.php'); // This loads way more than is needed here, but reduces code paths // and hence bugs. $moodlemia = moodle_marginalia::get_instance(); $profile = $moodlemia->get_profile($this->summary->summary_url()); $profile->emit_requires(); $PAGE->requires->js($blockpath . '/summary.js', true); // Get the course. This can't be passed as a GET parameter because this URL could be via the // Atom feed, and the Atom feed is generated exclusively by annotation code which doesn't know // that much about Moodle. So the handler has to query it based on a discussion ID or the like. $this->course = null; $this->courseid = $this->summary->handler->courseid; if (null != $this->courseid) { if (!($this->course = $DB->get_record("course", array('id' => $this->courseid)))) { error("Course ID is incorrect"); } // Ok, now this is probably very wrong. If the user looks for annotations within a course, // it requires a login. Without the course (i.e. in a more general search), it doesn't! // I would eleminate this, but I don't really know how Moodle security works. #geof# if ($this->course->category) { require_login($this->course->id); } } // #geof#: not quite correct - should fetch the URL from the summary object $PAGE->set_url('/mod/forum/summary.php'); if (null != $this->course) { $PAGE->set_title($this->course->shortname . ": " . get_string('summary_title', ANNOTATION_STRINGS)); $PAGE->set_heading($this->course->fullname); } else { $PAGE->set_title(get_string('summary_title', ANNOTATION_STRINGS)); $PAGE->set_heading(get_string('summary_title', ANNOTATION_STRINGS)); } // #geof# Must change to split requires from inline JS: if ($this->logger && $this->logger->is_active()) { $this->logger->header_html(); } if (null != $this->course && $this->course->category) { $PAGE->navbar->add($this->course->shortname, $CFG->wwwroot . '/course/view.php?id=' . $this->course->id); } $PAGE->navbar->add(get_string('summary_title', ANNOTATION_STRINGS)); echo $OUTPUT->header(); $swwwroot = htmlspecialchars($CFG->wwwroot); if (isloggedin()) { $profile->emit_body(); $sannotationpath = s(ANNOTATION_PATH); echo "<script language='JavaScript' type='text/javascript'>\n" . "var annotationService = new RestAnnotationService('{$sannotationpath}/annotate.php', " . "{ csrfCookie: 'MoodleSession" . $CFG->sessioncookie . "', noPutDelete: true } );\n" . "window.annotationSummary = new AnnotationSummary('{$swwwroot}', {" . " \n annotationService: annotationService" . ",\n userid: " . (int) $USER->id . ",\n useLog: " . ($this->logger && $this->logger->is_active() ? 'true' : 'false') . ",\n csrfCookie: 'MoodleSession" . $CFG->sessioncookie . "'" . "} );\n" . "window.preferences = new Preferences( new RestPreferenceService('{$sannotationpath}/user-preference.php' ) );\n" . "</script>\n"; } // Needed later to determine whether a given annotation is a keyword $keywords = isloggedin() ? annotation_keywords_db::list_keywords($USER->id) : array(); $keywordhash = array(); for ($i = 0; $i < count($keywords); ++$i) { $keyword = $keywords[$i]; $keywordhash[$keyword->name] = true; } // print search header // * my annotations // * shared annotations // * instructor annotations // * annotations of my work echo "<form id='annotation-search' method='get' action='summary.php'>\n"; echo "<fieldset>\n"; echo "<label for=''>" . get_string('prompt_find', ANNOTATION_STRINGS) . "</label>\n"; if ($this->summary->ofuser) { echo "<input type='hidden' name='search-of' id='search-of' value='" . s($this->moodlemia->fullname($this->summary->ofuser)) . "'/>\n"; } if ($this->summary->user) { echo "<input type='hidden' name='u' id='u' value='" . s($this->moodlemia->fullname($this->summary->user)) . "'/>\n"; } echo "<input type='text' id='search-text' name='q' value='" . s($this->summary->text) . "'/>\n"; echo "<input type='submit' value='" . get_string('go') . "'/>\n"; echo "<input type='hidden' name='url' value='" . s($this->summary->url) . "'/>\n"; // echo $OUTPUT->help_icon( 'annotation_summary', ANNOTATION_STRINGS ); //'block_marginalia', get_string( 'summary_help', ANNOTATION_STRINGS ) ); echo "</fieldset>\n"; echo "</form>"; // If this page is an error, explain what it's about if ('range-mismatch' == $this->errorpage) { echo '<p class="error"><em class="range-error">!</em>' . get_string('summary_range_error', ANNOTATION_STRINGS) . "</p>\n"; } $a = new object(); $a->n = $annotations ? count($annotations) : 0; $a->m = $annotation_count; echo '<p id="query">' . get_string('prompt_search_desc', ANNOTATION_STRINGS, $a) . ' ' . $this->summary->desc_with_links(null) . ":</p>\n"; $cursection = null; $cursectiontype = null; $curuser = null; $cururl = null; // make sure some records came back if (null != $annotations) { // Convert $annotations to an indexable array (why isn't it? for efficiency with large data sets?) $annotationa = array(); foreach ($annotations as $annotation) { $annotationa[] = $annotation; } $ncols = 6; if (AN_SUMMARY_ORDER_TIME == $this->summary->orderby) { $ncols += 1; } echo '<table cellspacing="0" class="annotations">' . "\n"; for ($annotationi = 0; $annotationi < count($annotationa); ++$annotationi) { $annotation = $annotationa[$annotationi]; // Display a heading for each new section URL if ($annotation->section_type != $cursectiontype || $annotation->section_url != $cursection) { if ($cursection != null) { echo "</tbody>\n"; } echo "<thead><tr><th colspan='{$ncols}'>"; $a->section_type = htmlspecialchars($annotation->section_type); echo '<h3>' . s($annotation->section_type) . '</h3>: ' . "<a href='" . s($annotation->section_url) . "' title='" . get_string('prompt_section', ANNOTATION_STRINGS, $a) . "'>" . s($annotation->section_name) . "</a>"; if ($annotation->section_url != $this->summary->url) { $tsummary = $this->summary->derive(array('url' => $annotation->section_url)); $turl = $tsummary->summary_url(); echo "<a class='zoom' title='" . get_string('zoom_url_hover', ANNOTATION_STRINGS, $annotation) . "' href='" . s($turl) . "'>" . AN_FILTERICON_HTML . "</a>\n"; } echo '</th></tr></thead>' . "\n"; if (AN_SUMMARYHEADINGSTOP) { $this->show_column_headings($this->summary, 'top'); } echo '<tbody>' . "\n"; $cursection = $annotation->section_url; $cursectiontype = $annotation->section_type; $curuser = $annotation->userid; $cururl = null; } // For each new url, display the title and author if ($annotation->url != $cururl) { //|| $annotation->userid != $curUser ) { $cururl = $annotation->url; $curuser = $annotation->userid; echo "<tr class='fragment first'>"; // Figure out how many rows this source will span $nrows = 1; for ($j = $annotationi + 1; $j < count($annotationa); ++$j) { if ($annotationa[$j]->url != $cururl) { break; } $nrows += 1; } // Only prefix the URL with the site root if it doesn't already have a scheme // Only check for http and https schemes to prevent obscure attacks $url = $annotation->url; if (!(str_startswith($url, 'http://') || str_startswith($url, 'https://'))) { $url = $CFG->wwwroot . $annotation->url; } echo "<th rowspan='{$nrows}'>"; $url = MarginaliaHelper::isUrlSafe($url) ? $url : ''; $a->row_type = $annotation->row_type; $a->author = $this->moodlemia->fullname2($annotation->quote_author_firstname, $annotation->quote_author_lastname); echo "<a class='url' href='" . s($url) . "' title='" . get_string('prompt_row', ANNOTATION_STRINGS, $a) . "'>"; echo s($annotation->quote_title) . '</a>'; echo "<br/>by <span class='quote-author'>" . s($a->author) . "</span>\n"; // Link to filter only annotations by this user if (!$this->summary->ofuser || $annotation->quote_author_username != $this->summary->ofuser->username) { $tsummary = $this->summary->derive(array('ofuserid' => $annotation->quote_author_id)); $turl = $tsummary->summary_url(); $a->fullname = $this->moodlemia->fullname2($annotation->quote_author_firstname, $annotation->quote_author_lastname); echo $this->zoom_link($tsummary->summary_url(), get_string('zoom_author_hover', ANNOTATION_STRINGS, $a)); } echo "</th>\n"; } else { echo "<tr>"; } // Show the quoted text echo "<td class='quote'>"; p($annotation->quote); echo "</td>\n"; // Show the note echo "<td class='note'>"; if (!$annotation->note) { echo ' '; } else { echo s($annotation->note); } if (!$this->summary->exactmatch && array_key_exists($annotation->note, $keywordhash)) { $tsummary = $this->summary->derive(array('text' => $annotation->note, 'exactmatch' => true)); echo ' ' . $this->zoom_link($tsummary->summary_url(), get_string('zoom_match_hover', ANNOTATION_STRINGS)); } echo "</td>\n"; // Show annotation time (if requested) if (AN_SUMMARY_ORDER_TIME == $this->summary->orderby) { echo "<td class='modified'>" . s(date('Y-m-d G:i', $annotation->modified)) . "</td>\n"; } // Show edit controls or the user who created the annotation echo "<td class='user" . (isloggedin() && $annotation->userid == $USER->id ? ' isloginuser' : '') . "'>\n"; // Smartquote button if (AN_USESMARTQUOTE) { // $SMARTQUOTE_SYMBOL = AN_SMARTQUOTEICON_PHP; //'♺'; $sqid = s('sq' . $annotation->id); $sqtitle = get_string('smartquote_annotation', ANNOTATION_STRINGS); echo "<button class='smartquote' id='{$sqid}' title='{$sqtitle}'>" . AN_SMARTQUOTEICON_HTML . "</button>\n"; } // Controls for current user if (isloggedin() && $annotation->userid == $USER->id) { $delid = s('del' . $annotation->id); $deltitle = get_string('js_delete_annotation_button', ANNOTATION_STRINGS); echo "<button class='delete-button' id='{$delid}' title='{$deltitle}'>x</button>\n"; } // User name (or "me" for current user) $displayusername = s($this->moodlemia->fullname2($annotation->firstname, $annotation->lastname)); $hiddenusername = ''; $class = 'user-name'; if (isloggedin() && $annotation->userid == $USER->id) { $hiddenusername = "******"; $displayusername = get_string('me', ANNOTATION_STRINGS); $class = ''; } $url = $CFG->wwwroot . $annotation->url; if (MarginaliaHelper::isUrlSafe($url)) { echo "<a class='{$class}' onclick='setAnnotationUser(\"" . s($annotation->userid) . "\")' href='" . s($url) . "'>" . "{$displayusername}</a>\n"; } else { echo "<span class='{$class}'>{$displayusername}</span>\n"; } echo $hiddenusername; // Link to filter only annotations by this user if (!$this->summary->user || $annotation->userid != $this->summary->user->username) { $tsummary = $this->summary->derive(array('userid' => $annotation->userid)); $turl = $tsummary->summary_url(); $a->fullname = $this->moodlemia->fullname2($annotation->firstname, $annotation->lastname); echo $this->zoom_link($tsummary->summary_url(), get_string('zoom_user_hover', ANNOTATION_STRINGS, $a)); } echo "</td>\n"; echo "</tr>\n"; } // Build scripts for individual buttons echo "<script type='text/javascript'>\n"; for ($annotationi = 0; $annotationi < count($annotationa); ++$annotationi) { $annotation = $annotationa[$annotationi]; if (AN_USESMARTQUOTE) { // HTML ID of smartquote button $sqid = s('sq' . $annotation->id); $tuserid = s($annotation->userid); echo " addEvent(document.getElementById('{$sqid}'),'click',function() {" . " window.annotationSummary.quote('{$sqid}','{$tuserid}'); } );"; } if (isloggedin() && $annotation->userid == $USER->id) { // HTML ID of delete button $delid = s('del' . $annotation->id); echo " addEvent(document.getElementById('{$delid}'),'click',function() {" . " window.annotationSummary.deleteAnnotation('{$delid}'," . (int) $annotation->id . "); } );\n"; } } echo "</script>\n"; if ($cururl != null) { echo "</tbody>\n"; } if (!AN_SUMMARYHEADINGSTOP) { $this->show_column_headings(''); } echo "</table>\n"; } marginalia_summary_lib::show_result_pages($this->first, $annotation_count, $this->maxrecords, $this->summary->summary_url('{first}')); /* // Show the list of result pages $npages = ceil( $annotation_count / $this->maxrecords ); if ( $npages > 1 ) { $this_page = 1 + floor( ( $this->first - 1 ) / $this->maxrecords ); echo "<ol class='result-pages'>\n"; for ( $i = 1; $i <= $npages; ++$i ) { if ( $i == $this_page ) echo " <li>".$i."</li>\n"; else echo " <li><a href='".s($this->summary->summary_url('{first}')."'>".$i."</a></li>\n"; } echo "</ol>\n"; } */ //$moodlePath = getMoodlePath( ); // Link for sorting by date or document order if ($this->summary->orderby == AN_SUMMARY_ORDER_DOCUMENT) { $tsummary = $this->summary->derive(array('orderby' => AN_SUMMARY_ORDER_TIME)); echo "<p><a href='" . s($tsummary->summary_url()) . "'>" . get_string('summary_sort_time', ANNOTATION_STRINGS) . "</a></p>\n"; } else { $tsummary = $this->summary->derive(array('orderby' => AN_SUMMARY_ORDER_DOCUMENT)); echo "<p><a href='" . s($tsummary->summary_url()) . "'>" . get_string('summary_sort_document', ANNOTATION_STRINGS) . "</a></p>\n"; } /* Feed removed because Moodle should require a login for it to be of much use, and the feed reader would then need to authenticate. So it's likely to be more frustrating than useful. // Provide a feed URL. I don't know how to do authentication for the feed, so for now // if a login is required I won't include the feature. if ( ! ANNOTATION_REQUIRE_USER ) { $tsummary = $this->summary->derive( array( 'orderby' => AN_SUMMARY_ORDER_TIME ) ); $turl = $tsummary->get_feed_url( 'atom' ); echo "<p class='feed' title='".get_string( 'atom_feed', ANNOTATION_STRINGS ) ."'><a href='".s($turl)."'><img border='0' alt='" .get_string( 'atom_feed', ANNOTATION_STRINGS )."' src='".s( $CFG->wwwroot )."/pix/i/rss.gif'/>" . '</a> '.get_string( 'atom_feed_desc', ANNOTATION_STRINGS )."</p>\n"; } */ echo "<p><a href='help.php?component=block_marginalia&topic=annotation_summary'>" . get_string('annotation_summary_help_link', ANNOTATION_STRINGS) . '</a></p>'; $OUTPUT->footer($this->course); $logurl = $_SERVER['REQUEST_URI']; $urlparts = parse_url($logurl); $logurl = array_key_exists('query', $urlparts) ? $urlparts['query'] : null; $this->moodlemia->moodle_log('summary', 'summary.php' . ($logurl ? '?' . $logurl : ''), $this->summary->desc(null)); // Marginalia logging if ($this->logger && $this->logger->is_active()) { $this->logger->summarizeAnnotations($this->summary->summary_url(), $this->summary->desc()); } }
function doDeleteAnnotation($annotation) { global $USER, $DB; if (!$this->can_annotate($annotation->url)) { $this->httpError(403, 'Forbidden', 'User lacks permission to annotate.'); return False; } else { $DB->delete_records(AN_DBTABLE, array('id' => $annotation->id)); $DB->delete_records(AN_READ_TABLE, array('annotationid' => $annotation->id)); if ($this->extService) { $extService = $this->extService; $extService->deleteAnnotation($annotation->id); } $moodlemia = moodle_marginalia::get_instance(); $logurl = "annotate.php?id=" . $annotation->id; $moodlemia->moodle_log('delete', $logurl, $annotation->id); return True; } }
/** * Print a forum post * * @global object * @global object * @uses FORUM_MODE_THREADED * @uses PORTFOLIO_FORMAT_PLAINHTML * @uses PORTFOLIO_FORMAT_FILE * @uses PORTFOLIO_FORMAT_RICHHTML * @uses PORTFOLIO_ADD_TEXT_LINK * @uses CONTEXT_MODULE * @param object $post The post to print. * @param object $discussion * @param object $forum * @param object $cm * @param object $course * @param boolean $ownpost Whether this post belongs to the current user. * @param boolean $reply Whether to print a 'reply' link at the bottom of the message. * @param boolean $link Just print a shortened version of the post as a link to the full post. * @param string $footer Extra stuff to print after the message. * @param string $highlight Space-separated list of terms to highlight. * @param int $post_read true, false or -99. If we already know whether this user * has read this post, pass that in, otherwise, pass in -99, and this * function will work it out. * @param boolean $dummyifcantsee When forum_user_can_see_post says that * the current user can't see this post, if this argument is true * (the default) then print a dummy 'you can't see this post' post. * If false, don't output anything at all. * @param bool|null $istracked * @return void */ function forum_print_post($post, $discussion, $forum, &$cm, $course, $ownpost = false, $reply = false, $link = false, $footer = "", $highlight = "", $postisread = null, $dummyifcantsee = true, $istracked = null, $return = false) { global $USER, $CFG, $OUTPUT; require_once $CFG->libdir . '/filelib.php'; // String cache static $str; $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id); $post->course = $course->id; $post->forum = $forum->id; $post->message = file_rewrite_pluginfile_urls($post->message, 'pluginfile.php', $modcontext->id, 'mod_forum', 'post', $post->id); // caching if (!isset($cm->cache)) { $cm->cache = new stdClass(); } if (!isset($cm->cache->caps)) { $cm->cache->caps = array(); $cm->cache->caps['mod/forum:viewdiscussion'] = has_capability('mod/forum:viewdiscussion', $modcontext); $cm->cache->caps['moodle/site:viewfullnames'] = has_capability('moodle/site:viewfullnames', $modcontext); $cm->cache->caps['mod/forum:editanypost'] = has_capability('mod/forum:editanypost', $modcontext); $cm->cache->caps['mod/forum:splitdiscussions'] = has_capability('mod/forum:splitdiscussions', $modcontext); $cm->cache->caps['mod/forum:deleteownpost'] = has_capability('mod/forum:deleteownpost', $modcontext); $cm->cache->caps['mod/forum:deleteanypost'] = has_capability('mod/forum:deleteanypost', $modcontext); $cm->cache->caps['mod/forum:viewanyrating'] = has_capability('mod/forum:viewanyrating', $modcontext); $cm->cache->caps['mod/forum:exportpost'] = has_capability('mod/forum:exportpost', $modcontext); $cm->cache->caps['mod/forum:exportownpost'] = has_capability('mod/forum:exportownpost', $modcontext); } if (!isset($cm->uservisible)) { $cm->uservisible = coursemodule_visible_for_user($cm); } if ($istracked && is_null($postisread)) { $postisread = forum_tp_is_post_read($USER->id, $post); } if (!forum_user_can_see_post($forum, $discussion, $post, NULL, $cm)) { $output = ''; if (!$dummyifcantsee) { if ($return) { return $output; } echo $output; return; } $output .= html_writer::tag('a', '', array('id' => 'p' . $post->id)); $output .= html_writer::start_tag('div', array('class' => 'forumpost clearfix')); $output .= html_writer::start_tag('div', array('class' => 'row header')); $output .= html_writer::tag('div', '', array('class' => 'left picture')); // Picture if ($post->parent) { $output .= html_writer::start_tag('div', array('class' => 'topic')); } else { $output .= html_writer::start_tag('div', array('class' => 'topic starter')); } $output .= html_writer::tag('div', get_string('forumsubjecthidden', 'forum'), array('class' => 'subject')); // Subject $output .= html_writer::tag('div', get_string('forumauthorhidden', 'forum'), array('class' => 'author')); // author $output .= html_writer::end_tag('div'); $output .= html_writer::end_tag('div'); // row $output .= html_writer::start_tag('div', array('class' => 'row')); $output .= html_writer::tag('div', ' ', array('class' => 'left side')); // Groups $output .= html_writer::tag('div', get_string('forumbodyhidden', 'forum'), array('class' => 'content')); // Content $output .= html_writer::end_tag('div'); // row $output .= html_writer::end_tag('div'); // forumpost if ($return) { return $output; } echo $output; return; } if (empty($str)) { $str = new stdClass(); $str->edit = get_string('edit', 'forum'); $str->delete = get_string('delete', 'forum'); $str->reply = get_string('reply', 'forum'); $str->parent = get_string('parent', 'forum'); $str->pruneheading = get_string('pruneheading', 'forum'); $str->prune = get_string('prune', 'forum'); $str->displaymode = get_user_preferences('forum_displaymode', $CFG->forum_displaymode); $str->markread = get_string('markread', 'forum'); $str->markunread = get_string('markunread', 'forum'); } $discussionlink = new moodle_url('/mod/forum/discuss.php', array('d' => $post->discussion)); // Build an object that represents the posting user $postuser = new stdClass(); $postuser->id = $post->userid; $postuser->firstname = $post->firstname; $postuser->lastname = $post->lastname; $postuser->imagealt = $post->imagealt; $postuser->picture = $post->picture; $postuser->email = $post->email; // Some handy things for later on $postuser->fullname = fullname($postuser, $cm->cache->caps['moodle/site:viewfullnames']); $postuser->profilelink = new moodle_url('/user/view.php', array('id' => $post->userid, 'course' => $course->id)); // Prepare the groups the posting user belongs to if (isset($cm->cache->usersgroups)) { $groups = array(); if (isset($cm->cache->usersgroups[$post->userid])) { foreach ($cm->cache->usersgroups[$post->userid] as $gid) { $groups[$gid] = $cm->cache->groups[$gid]; } } } else { $groups = groups_get_all_groups($course->id, $post->userid, $cm->groupingid); } // Prepare the attachements for the post, files then images list($attachments, $attachedimages) = forum_print_attachments($post, $cm, 'separateimages'); // Determine if we need to shorten this post $shortenpost = $link && strlen(strip_tags($post->message)) > $CFG->forum_longpost; // Prepare an array of commands $commands = array(); // SPECIAL CASE: The front page can display a news item post to non-logged in users. // Don't display the mark read / unread controls in this case. if ($istracked && $CFG->forum_usermarksread && isloggedin()) { $url = new moodle_url($discussionlink, array('postid' => $post->id, 'mark' => 'unread')); $text = $str->markunread; if (!$postisread) { $url->param('mark', 'read'); $text = $str->markread; } if ($str->displaymode == FORUM_MODE_THREADED) { $url->param('parent', $post->parent); } else { $url->set_anchor('p' . $post->id); } $commands[] = array('url' => $url, 'text' => $text); } // Zoom in to the parent specifically if ($post->parent) { $url = new moodle_url($discussionlink); if ($str->displaymode == FORUM_MODE_THREADED) { $url->param('parent', $post->parent); } else { $url->set_anchor('p' . $post->parent); } $commands[] = array('url' => $url, 'text' => $str->parent); } // Hack for allow to edit news posts those are not displayed yet until they are displayed $age = time() - $post->created; if (!$post->parent && $forum->type == 'news' && $discussion->timestart > time()) { $age = 0; } if ($ownpost && $age < $CFG->maxeditingtime || $cm->cache->caps['mod/forum:editanypost']) { $commands[] = array('url' => new moodle_url('/mod/forum/post.php', array('edit' => $post->id)), 'text' => $str->edit); } if ($cm->cache->caps['mod/forum:splitdiscussions'] && $post->parent && $forum->type != 'single') { $commands[] = array('url' => new moodle_url('/mod/forum/post.php', array('prune' => $post->id)), 'text' => $str->prune, 'title' => $str->pruneheading); } if ($ownpost && $age < $CFG->maxeditingtime && $cm->cache->caps['mod/forum:deleteownpost'] || $cm->cache->caps['mod/forum:deleteanypost']) { $commands[] = array('url' => new moodle_url('/mod/forum/post.php', array('delete' => $post->id)), 'text' => $str->delete); } if ($reply) { $commands[] = array('url' => new moodle_url('/mod/forum/post.php', array('reply' => $post->id)), 'text' => $str->reply); } if ($CFG->enableportfolios && ($cm->cache->caps['mod/forum:exportpost'] || $ownpost && $cm->cache->caps['mod/forum:exportownpost'])) { $p = array('postid' => $post->id); require_once $CFG->libdir . '/portfoliolib.php'; $button = new portfolio_add_button(); $button->set_callback_options('forum_portfolio_caller', array('postid' => $post->id), '/mod/forum/locallib.php'); if (empty($attachments)) { $button->set_formats(PORTFOLIO_FORMAT_PLAINHTML); } else { $button->set_formats(PORTFOLIO_FORMAT_RICHHTML); } $porfoliohtml = $button->to_html(PORTFOLIO_ADD_TEXT_LINK); if (!empty($porfoliohtml)) { $commands[] = $porfoliohtml; } } // Finished building commands // Begin output $output = ''; if ($istracked) { if ($postisread) { $forumpostclass = ' read'; } else { $forumpostclass = ' unread'; $output .= html_writer::tag('a', '', array('name' => 'unread')); } } else { // ignore trackign status if not tracked or tracked param missing $forumpostclass = ''; } $topicclass = ''; if (empty($post->parent)) { $topicclass = ' firstpost starter'; } $output .= html_writer::tag('a', '', array('id' => 'p' . $post->id)); $output .= html_writer::start_tag('div', array('class' => 'forumpost clearfix' . $forumpostclass . $topicclass)); $output .= html_writer::start_tag('div', array('class' => 'row header clearfix')); $output .= html_writer::start_tag('div', array('class' => 'left picture')); $output .= $OUTPUT->user_picture($postuser, array('courseid' => $course->id)); $output .= html_writer::end_tag('div'); $output .= html_writer::start_tag('div', array('class' => 'topic' . $topicclass)); $postsubject = $post->subject; if (empty($post->subjectnoformat)) { $postsubject = format_string($postsubject); } $output .= html_writer::tag('div', $postsubject, array('class' => 'subject')); $by = new stdClass(); $by->name = html_writer::link($postuser->profilelink, $postuser->fullname); $by->date = userdate($post->modified); $output .= html_writer::tag('div', get_string('bynameondate', 'forum', $by), array('class' => 'author')); $output .= html_writer::end_tag('div'); //topic $output .= html_writer::end_tag('div'); //row $output .= html_writer::start_tag('div', array('class' => 'row maincontent clearfix')); $output .= html_writer::start_tag('div', array('class' => 'left')); $groupoutput = ''; if ($groups) { $groupoutput = print_group_picture($groups, $course->id, false, true, true); } if (empty($groupoutput)) { $groupoutput = ' '; } $output .= html_writer::tag('div', $groupoutput, array('class' => 'grouppictures')); $output .= html_writer::end_tag('div'); //left side $output .= html_writer::start_tag('div', array('class' => 'no-overflow')); $output .= html_writer::start_tag('div', array('class' => 'content')); if (!empty($attachments)) { $output .= html_writer::tag('div', $attachments, array('class' => 'attachments')); } $options = new stdClass(); $options->para = false; $options->trusted = $post->messagetrust; $options->context = $modcontext; if ($shortenpost) { // Prepare shortened version $postclass = 'shortenedpost'; $postcontent = format_text(forum_shorten_post($post->message), $post->messageformat, $options, $course->id); $postcontent .= html_writer::link($discussionlink, get_string('readtherest', 'forum')); $postcontent .= html_writer::tag('span', '(' . get_string('numwords', 'moodle', count_words(strip_tags($post->message))) . ')...', array('class' => 'post-word-count')); } else { // Prepare whole post $postclass = 'fullpost'; $postcontent = format_text($post->message, $post->messageformat, $options, $course->id); if (!empty($highlight)) { $postcontent = highlight($highlight, $postcontent); } $postcontent .= html_writer::tag('div', $attachedimages, array('class' => 'attachedimages')); } // #marginalia begin // Write out the margin. It goes before the content, then floats right. global $PAGE; $miamoodle = moodle_marginalia::get_instance(); $miaprofile = $miamoodle->get_profile($PAGE->url->out(false)); if ($miaprofile) { $output .= $miaprofile->output_margin(); } // #marginalia end // Output the post content $output .= html_writer::tag('div', $postcontent, array('class' => 'posting ' . $postclass)); $output .= html_writer::end_tag('div'); // Content $output .= html_writer::end_tag('div'); // Content mask $output .= html_writer::end_tag('div'); // Row $output .= html_writer::start_tag('div', array('class' => 'row side')); $output .= html_writer::tag('div', ' ', array('class' => 'left')); $output .= html_writer::start_tag('div', array('class' => 'options clearfix')); // Output ratings if (!empty($post->rating)) { $output .= html_writer::tag('div', $OUTPUT->render($post->rating), array('class' => 'forum-post-rating')); } // Output the commands $commandhtml = array(); foreach ($commands as $command) { if (is_array($command)) { $commandhtml[] = html_writer::link($command['url'], $command['text']); } else { $commandhtml[] = $command; } } // #marginalia begin // Ack. Moodle assumes that commands should be links. This doesn't work // for the quote button, because it has to call some JS to get the quote. if ($miaprofile) { $commandhtml[] = $miaprofile->output_quote_button(); } // #marginalia end $output .= html_writer::tag('div', implode(' | ', $commandhtml), array('class' => 'commands')); // Output link to post if required if ($link) { if ($post->replies == 1) { $replystring = get_string('repliesone', 'forum', $post->replies); } else { $replystring = get_string('repliesmany', 'forum', $post->replies); } $output .= html_writer::start_tag('div', array('class' => 'link')); $output .= html_writer::link($discussionlink, get_string('discussthistopic', 'forum')); $output .= ' (' . $replystring . ')'; $output .= html_writer::end_tag('div'); // link } // Output footer if required if ($footer) { $output .= html_writer::tag('div', $footer, array('class' => 'footer')); } // Close remaining open divs $output .= html_writer::end_tag('div'); // content $output .= html_writer::end_tag('div'); // row $output .= html_writer::end_tag('div'); // forumpost // Mark the forum post as read if required if ($istracked && !$CFG->forum_usermarksread && !$postisread) { forum_tp_mark_post_read($USER->id, $post, $forum->id); } if ($return) { return $output; } echo $output; return; }
$url = "discuss.php?d={$discussion->id}&fromforum={$discussion->forum}&move={$courseforum->id}"; $forummenu[$url] = format_string($courseforum->name, true); } } if (!empty($forummenu)) { echo "<div style=\"float:right;\">"; echo popup_form("{$CFG->wwwroot}/mod/forum/", $forummenu, "forummenu", "", get_string("movethisdiscussionto", "forum"), "", "", true); echo "</div>"; } } } // Annotation controls (help, user dropdown, link to summary page) echo "</td>\n<td id='annotation-controls'>"; moodle_marginalia::show_help('forum'); moodle_marginalia::show_user_dropdown($refurl, true); echo moodle_marginalia::summary_link_html($refurl, $USER->username); echo "</td></tr></table>"; if (!empty($forum->blockafter) && !empty($forum->blockperiod)) { $a->blockafter = $forum->blockafter; $a->blockperiod = get_string('secondstotime' . $forum->blockperiod); notify(get_string('thisforumisthrottled', 'forum', $a)); } if ($forum->type == 'qanda' && !has_capability('mod/forum:viewqandawithoutposting', $modcontext) && !forum_user_has_posted($forum->id, $discussion->id, $USER->id)) { notify(get_string('qandanotify', 'forum')); } if (isset($discussionmoved)) { notify(get_string("discussionmoved", "forum", format_string($forum->name, true))); } /// Print the actual discussion if (!$canviewdiscussion) { notice(get_string('noviewdiscussionspermission', 'forum'));
function show_user_dropdown($refurl) { global $USER; $summary = annotation_summary_query::from_url($refurl); $userlist = get_records_sql($summary->list_users_sql()); $annotationuserid = moodle_marginalia::get_userid(); $showannotationspref = moodle_marginalia::get_show_annotations_pref() == 'true'; echo "<select name='anuser' id='anuser' onchange='window.moodleMarginalia.changeAnnotationUser(this,\"{$refurl}\");'>\n"; $selected = $showannotationspref ? '' : " selected='selected' "; echo " <option {$selected} value=''>" . get_string('hide_annotations', ANNOTATION_STRINGS) . "</option>\n"; if (!isguest()) { $selected = $showannotationspref && ($USER->username == $annotationuserid ? "selected='selected' " : '') ? " selected='selected' " : ''; echo " <option {$selected}" . "value='" . s($USER->username) . "'>" . get_string('my_annotations', ANNOTATION_STRINGS) . "</option>\n"; } if ($userlist) { foreach ($userlist as $user) { if ($user->username != $USER->username) { $selected = $showannotationspref && ($user->id == $annotationuserid ? "selected='selected' " : '') ? " selected='selected' " : ''; echo " <option {$selected}" . "value='" . s($user->username) . "'>" . s($user->firstname . ' ' . $user->lastname) . "</option>\n"; } } } // Show item for all users if (true) { $selected = $showannotationspref && ('*' == $annotationuserid ? "selected='selected' " : '') ? " selected='selected' " : ''; echo " <option {$selected} value='*'>" . get_string('all_annotations', ANNOTATION_STRINGS) . "</option>\n"; } echo "</select>\n"; }