echo "<option value='private'".('private'==$annotation->access?"selected='selected'":'').'>'.get_string( 'private', ANNOTATION_STRINGS )."</option>\n"; echo "<option value='author'".('author'==$annotation->access?"selected='selected'":'').'>'.get_string( 'author', ANNOTATION_STRINGS )."</option>\n"; echo "<option value='teacher'".('teacher'==$annotation->access?"selected='selected'":'').'>'.get_string( 'teacher', ANNOTATION_STRINGS )."</option>\n"; echo "<option value='author teacher'".('author teacher'==$annotation->access?"selected='selected'":'').'>'.get_string( 'author+teacher', ANNOTATION_STRINGS )."</option>\n"; echo "<option value='public'".('public'==$annotation->access?"selected='selected'":'').'>'.get_string( 'public', ANNOTATION_STRINGS )."</option>\n"; echo "</select>\n"; */ echo "<button class='delete-button' onclick='window.annotationSummary.deleteAnnotation({$annotation->id});'>x</button>"; echo "</td>\n"; } else { if (!in_array('user', $excludeFields)) { echo "<td class='anuser'>"; $url = $CFG->wwwroot . $annotation->url; //if ( $annotation->userid && $annotation->userid != $USER->username ) // $url .= "&anuser="******"<a onclick='setAnnotationUser(\"" . htmlspecialchars($annotation->userid) . "\")' href='" . htmlspecialchars($url) . "'>" . htmlspecialchars($annotation->note_author) . "</a>"; } echo "</td>\n"; } } } echo "</tr>\n"; } if ($curUrl != null) { echo "</tbody>\n"; } echo "</table>\n"; // print the page content // echo "<p><a href='summary.php?course=$courseId'>Show all of my annotations for this course</a></p>\n"; }
function setLink($link) { if (!$link || MarginaliaHelper::isUrlSafe($link)) { $this->link = $link; } }
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 show_html($summary, $annotations) { global $CFG, $USER; // 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 = $summary->handler->courseid; if (null != $this->courseid) { if (!($this->course = get_record("course", "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); } } // Keep for debugging: // echo "<h2>Query</h2><pre>".$query->sql( 'a.id' )."</pre>"; // Show header $swwwroot = htmlspecialchars($CFG->wwwroot); $this->show_header(); $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 $username = $summary->user ? $summary->user->username : ''; $ofusername = $summary->ofuser ? $summary->ofuser->username : ''; echo "<form id='annotation-search' method='get' action='summary.php'>\n"; echo "<fieldset>\n"; echo "<label for='search-of'>" . get_string('prompt_find', ANNOTATION_STRINGS) . "</label>\n"; echo "<input type='hidden' name='search-of' id='search-of' value='" . s($ofusername) . "'/>\n"; echo "<input type='hidden' name='u' id='u' value='" . s($username) . "'/>\n"; echo "<input type='text' id='search-text' name='q' value='" . s($summary->text) . "'/>\n"; echo "<input type='submit' value='" . get_string('go') . "'/>\n"; echo "<input type='hidden' name='url' value='" . s($summary->url) . "'/>\n"; helpbutton('annotation_summary', get_string('summary_help', ANNOTATION_STRINGS), 'block_marginalia'); 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"; } echo '<p id="query">' . get_string('prompt_search_desc', ANNOTATION_STRINGS) . ' ' . $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; 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 != $summary->url) { $tsummary = $summary->for_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('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 = $annotation->quote_author_fullname; 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($annotation->quote_author_fullname) . "</span>\n"; // Link to filter only annotations by this user if (!$summary->ofuser || $annotation->quote_author_username != $summary->ofuser->username) { $tuser = get_record('user', 'username', $annotation->quote_author_username); if ($tuser) { $tsummary = $summary->for_ofuser($tuser); $turl = $tsummary->summary_url(); $a->fullname = $annotation->quote_author_fullname; echo "<a class='zoom' title='" . get_string('zoom_author_hover', ANNOTATION_STRINGS, $a) . "' href='" . s($turl) . "'>" . AN_FILTERICON_HTML . "</a>\n"; } } 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 { p($annotation->note); } if (!$summary->exactmatch && array_key_exists($annotation->note, $keywordhash)) { $tsummary = $summary->for_text($annotation->note, true); echo "<a class='zoom' title='" . get_string('zoom_match_hover', ANNOTATION_STRINGS) . "' href='" . s($tsummary->summary_url()) . "'>" . AN_FILTERICON_HTML . "</a>\n"; } echo "</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) { $AN_SUN_SYMBOL = '○'; $AN_MOON_SYMBOL = '◆'; $access_str = AN_ACCESS_PUBLIC & $annotation->access_perms ? 'public' : 'private'; echo "<button class='share-button access-{$access_str}' onclick='window.annotationSummary.shareAnnotationPublicPrivate(this,{$annotation->id});'>" . ($annotation->access_perms & AN_ACCESS_PUBLIC ? $AN_SUN_SYMBOL : $AN_MOON_SYMBOL) . "</button>"; echo "<button class='delete-button' onclick='window.annotationSummary.deleteAnnotation({$annotation->id});'>x</button>\n"; } // User name (or "me" for current user) $displayusername = s($annotation->username); $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 (!$summary->user || $annotation->userid != $summary->user->username) { $tuser = get_record('user', 'username', $annotation->username); if ($tuser) { $tsummary = $summary->for_user($tuser); $turl = $tsummary->summary_url(); $a->fullname = $annotation->fullname; echo "<a class='zoom' title='" . get_string('zoom_user_hover', ANNOTATION_STRINGS, $a) . "' href='" . s($turl) . "'>" . AN_FILTERICON_HTML . "</a>\n"; } } 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]; $sqid = s('sq' . $annotation->id); $tuserid = s($annotation->userid); echo " addEvent(document.getElementById('{$sqid}'),'click',function() {" . " window.annotationSummary.quote('{$sqid}','{$tuserid}'); } );"; } echo "</script>\n"; if ($cururl != null) { echo "</tbody>\n"; } if (!AN_SUMMARYHEADINGSTOP) { $this->show_column_headings(''); } echo "</table>\n"; } //$moodlePath = getMoodlePath( ); // 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) { $turl = $summary->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"; } print_footer($this->course); $logurl = $_SERVER['REQUEST_URI']; $urlparts = parse_url($logurl); $logurl = array_key_exists('query', $urlparts) ? $urlparts['query'] : null; add_to_log(null, 'annotation', 'summary', 'summary.php' . ($logurl ? '?' . $logurl : ''), $summary->desc(null)); }
/** * Set annotation fields based on parameters (e.g. from $_POST) * For updates, first retrieve the stored annotation, then update it here. * If this fails, the passed annotation object may have already been altered. * Different implementations may have different annotation objects. All should * be compatible with this code if they have the appropriate getters and setters. */ function annotationFromParams(&$annotation, &$params) { // ID // must be setAnnotationId, not setId, because of a conflict with a base class method in OJS if (array_key_exists('id', $params)) { $id = $params['id']; $annotation->setAnnotationId($id); } // UserId if (array_key_exists('userid', $params)) { $userid = $params['userid']; $annotation->setUserId($userid); } // UserName if (array_key_exists('username', $params)) { $userName = $params['username']; $annotation->setUserName($userName); } // Sequence Range if (array_key_exists('sequence-range', $params)) { $sequenceRange = new SequenceRange(); $sequenceRange->fromString($params['sequence-range']); $annotation->setSequenceRange($sequenceRange); } // XPath Range if (array_key_exists('xpath-range', $params)) { $xpathRange = new XPathRange(); $xpathRange->fromString($params['xpath-range']); if (!XPathPoint::isXPathSafe($xpathRange->start->getPathStr()) || !XPathPoint::isXPathSafe($xpathRange->end->getPathStr())) { return XPATH_SECURITY_ERROR; } $annotation->setXPathRange($xpathRange); } // URL if (array_key_exists('url', $params)) { $url = $params['url']; if (!$url || !MarginaliaHelper::isUrlSafe($url)) { return URL_SCHEME_ERROR; } $annotation->setUrl($url); } // Note if (array_key_exists('note', $params)) { $note = $params['note']; $annotation->setNote($note); } // Quote if (array_key_exists('quote', $params)) { $quote = $params['quote']; $annotation->setQuote($quote); } // QuoteTitle if (array_key_exists('quote_title', $params)) { $quoteTitle = $params['quote_title']; $annotation->setQuoteTitle($quoteTitle); } // QuoteAuthorId if (array_key_exists('quote_author_id', $params)) { $quoteAuthorId = $params['quote_author_id']; $annotation->setQuoteAuthorId($quoteAuthorId); } // QuoteAuthorName if (array_key_exists('quote_author_name', $params)) { $quoteAuthorName = $params['quote_author_name']; $annotation->setQuoteAuthorName($quoteAuthorName); } // Access if (array_key_exists('access', $params)) { $access = $params['access']; if (!Annotation::isAccessValid($access)) { return ACCESS_VALUE_ERROR; } $annotation->setAccess($access); } // Action if (array_key_exists('action', $params)) { $action = $params['action']; if (!Annotation::isActionValid($action)) { return ACTION_VALUE_ERROR; } $annotation->setAction($action); } // Link if (array_key_exists('link', $params)) { $link = $params['link']; if ($link && !MarginaliaHelper::isUrlSafe($link)) { return URL_SCHEME_ERROR; } $annotation->setLink($link); } // Link Title if (array_key_exists('link_title', $params)) { $title = $params['link_title']; $annotation->setLinkTitle($title); } // Created if (array_key_exists('created', $params)) { $created = $params['created']; // TODO: verify date format $this->setCreated($created); } // Modified if (array_key_exists('modified', $params)) { $modified = $params['modified']; $this->setModified($modified); } // Version if (array_key_exists('version', $params)) { $version = $params['version']; $this->setVersion($version); } // Ok, I know in PHP it's traditional to return True for success, // but that requires the triple === which drives me nuts and is // easy to forget (and if ( f() ) won't work), so I'll go with the // old C / Unix tradition and return 0. return 0; }
/** * Set a link to another resource * In order to preclude the possibility of XSS attacks, only http or https * schemes are accepted. */ function setLink($link) { if (!$link || MarginaliaHelper::isUrlSafe($link)) { return $this->setData('link', $link); } else { return false; } }