Example #1
0
 /**
  * Convert to an Atom entry
  */
 function toAtom($tagHost, $servicePath)
 {
     return MarginaliaHelper::annotationToAtom($this, $tagHost, $servicePath);
 }
Example #2
0
                 			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";
 }
Example #3
0
 function listBodyParams()
 {
     return MarginaliaHelper::listBodyParams();
 }
Example #4
0
 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 '&#160;';
             } 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; //'&#9850;';
                 $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());
     }
 }
Example #5
0
 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 '&#160;';
             } 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; //'&#9850;';
                 $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 = '&#9675;';
                 $AN_MOON_SYMBOL = '&#9670;';
                 $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));
 }
Example #6
0
 function listBodyParams($forceStrip = false)
 {
     $method = $_SERVER['REQUEST_METHOD'];
     if ('POST' == $method) {
         $params = array();
         foreach (array_keys($_POST) as $param) {
             $params[$param] = $forceStrip ? stripslashes($_POST[$param]) : MarginaliaHelper::unfix_quotes($_POST[$param]);
         }
         return $params;
     } elseif ('PUT' == $method) {
         // Now for some joy.  PHP isn't clever enough to populate $_POST if the
         // Content-Type is application/x-www-form-urlencoded - it only does
         // that if the request method is POST.  It is, however, clever enough
         // to insert its bloody !@#$! slashes.  Bleargh.  (Actually, to be fair
         // the descriptions of PUT I have seen insist that it should accept a
         // full resource representation, not changed fields as I'm doing here.
         // In Atom, at least, that's to maintain database consistency.  I don't
         // think it's an issue here, so I haven't gotten around to doing it.)
         // Plus, how do I ensure the charset is respected correctly?  Hmph.
         // Should fail if not Content-Type: application/x-www-form-urlencoded; charset: UTF-8
         $fp = fopen('php://input', 'rb');
         $urlencoded = '';
         while ($data = fread($fp, 1024)) {
             $urlencoded .= $data;
         }
         parse_str($urlencoded, $params);
         // magic_quotes_gpc - the GPC stands for GET POST COOKIE, so should not affect PUT
         foreach (array_keys($params) as $param) {
             $params[$param] = $params[$param];
         }
         return $params;
     } else {
         return null;
     }
 }
Example #7
0
 function getBlocks($annotations, $url)
 {
     $infos = MarginaliaHelper::annotationsToRangeInfos($annotations);
     for ($i = 0; $i < count($infos); ++$i) {
         $infos[$i]->makeBlockLevel();
     }
     $infos = MarginaliaHelper::mergeRangeInfos($infos);
     header('Content-Type: application/xml');
     echo '<?xml version="1.0" encoding="utf-8"?>' . "\n";
     echo MarginaliaHelper::getRangeInfoXml($infos);
 }
Example #8
0
 /**
  * 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'];
         $this->setUserId($userid);
     }
     // 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);
     }
     // QuoteAuthor
     if (array_key_exists('quote_author', $params)) {
         $quoteAuthor = $params['quote_author'];
         $annotation->setQuoteAuthor($quoteAuthor);
     }
     // 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);
     }
     // 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;
 }
Example #9
0
 function show()
 {
     global $CFG;
     $search = $this->search;
     $this->errorpage = array_key_exists('error', $_GET) ? $_GET['error'] : null;
     $query = "SELECT count(*) FROM {$CFG->prefix}marginalia_event_log";
     $total_events = count_records_sql($query);
     $query = "SELECT e.id AS id, e.userid AS userid, e.service AS service, e.action AS action" . ", e.description AS description, e.object_type AS object_type" . ", e.object_id AS object_id, e.modified AS modified" . ", e.course as course" . ", concat(u.firstname, ' ', u.lastname) AS fullname" . ", a.sheet_type AS sheet_type" . ", a.quote AS quote" . ", a.note AS note" . ", a.object_type AS an_object_type" . ", a.object_id AS an_object_id" . ", concat(qu.firstname, ' ', qu.lastname) AS qu_fullname" . ", p.id AS p_id" . ", p.subject AS p_name" . ", p.discussion AS p_discussion" . ", p.created AS p_created" . ", d.name AS d_name" . ", d.id AS d_id" . ", c.shortname AS c_name" . " FROM {$CFG->prefix}marginalia_event_log e" . " LEFT OUTER JOIN {$CFG->prefix}course c ON c.id=e.course" . " LEFT OUTER JOIN {$CFG->prefix}marginalia_annotation_log a" . " ON (e.object_type=" . AN_OTYPE_ANNOTATION . " AND a.eventid=e.id)" . " LEFT OUTER JOIN {$CFG->prefix}user u ON u.id=e.userid" . " LEFT OUTER JOIN {$CFG->prefix}forum_posts p" . " ON (a.object_type=" . AN_OTYPE_POST . " AND p.id=a.object_id)" . " LEFT OUTER JOIN {$CFG->prefix}forum_discussions d" . " ON (a.object_type=" . AN_OTYPE_POST . " AND d.id=p.discussion)" . " LEFT OUTER JOIN {$CFG->prefix}USER qu " . " ON (e.object_type=" . AN_OTYPE_ANNOTATION . " AND qu.id=a.quote_author_id)" . " WHERE 1=1";
     if ($search->course) {
         $query .= " AND e.course=" . (int) $search->course . "\n";
     }
     if ($search->user) {
         $query .= " AND e.userid=" . (int) $search->user . "\n";
     }
     if ($search->discussion) {
         $query .= " AND d.id=" . (int) $search->discussion . "\n";
     }
     if ($search->object_type) {
         $query .= " AND e.object_type=" . (int) $search->object_type;
         if ($search->object_id) {
             $query .= " AND e.object_id=" . (int) $search->object_id;
         }
         $query .= "\n";
     }
     $query .= " ORDER BY e.modified DESC";
     //		echo "Query: $query\n";
     $events = get_records_sql($query, $search->first - 1, $this->maxrecords);
     echo "<p>" . $search->desc() . "</p>\n";
     echo "<table id='events'>\n";
     echo " <thead><tr>\n";
     echo "  <th>Time</th><th>Course</th><th>User</th><th>Service</th><th>Action</th><th>Description</th><th>Object</th>\n";
     if ($this->extracolumns) {
         echo "<th>Sheet</th><th>Quote</th><th>Note</th><th>Post</th><th>Discussion</th><th>Post Author</th><th>Posted</th>\n";
     }
     echo " </tr></thead><tbody>\n";
     if ($events && count($events)) {
         foreach ($events as $event) {
             echo " <tr>\n";
             echo "  <td>" . s(MarginaliaHelper::timeToIso($event->modified)) . "</td>\n";
             echo "  <td>" . s($event->c_name) . $this->zoom_link(array('course' => $event->course)) . "</td>\n";
             echo "  <td>" . s($event->fullname) . $this->zoom_link(array('user' => $event->userid)) . "</td>\n";
             echo "  <td>" . s($event->service) . "</td>\n";
             echo "  <td>" . s($event->action) . "</td>\n";
             echo "  <td>" . s($event->description) . "</td>\n";
             if (AN_OTYPE_ANNOTATION == $event->object_type) {
                 echo "<td>annotation #" . (int) $event->object_id . $this->zoom_link(array('object_type' => $event->object_type, 'object_id' => $event->object_id)) . "</td>\n";
                 if ($this->extracolumns) {
                     if (AN_OTYPE_ANNOTATION == $event->object_type) {
                         echo "<td>" . s(annotation_globals::sheet_str($event->sheet_type)) . "</td>\n";
                         echo "<td>" . s($event->quote) . "</td>\n";
                         echo "<td>" . s($event->note) . "</td>\n";
                         if (AN_OTYPE_POST == $event->an_object_type) {
                             $url = $CFG->wwwroot . '/mod/forum/permalink.php?p=' . $event->p_id;
                             echo "<td><a href='" . s($url) . "'>" . s($event->p_id) . "</a></td>\n";
                             echo "<td>" . s($event->d_name) . $this->zoom_link(array('d' => $event->d_id)) . "</td>\n";
                             echo "<td>" . s($event->qu_fullname) . "</a></td>\n";
                             echo "<td>" . s(MarginaliaHelper::timeToIso($event->p_created)) . "</td>\n";
                         } else {
                             echo "<td colspan='4'></td>\n";
                         }
                     } else {
                         echo "<td colspan='8'></td>\n";
                     }
                 }
             } else {
                 if (AN_OTYPE_POST == $event->object_type) {
                     echo "<td>post #" . (int) $event->object_id . $this->zoom_link(array('object_type' => $event->object_type, 'object_id' => $event->object_id)) . "</td>\n";
                     echo "<td colspan='8'></td>\n";
                 } else {
                     echo "<td colspan='9'></td>\n";
                 }
             }
             echo " </tr>\n";
         }
         echo "</tbody></table>\n";
         $tsearch = $search->derive();
         $tsearch->first = '{first}';
         marginalia_summary_lib::show_result_pages($search->first, $total_events, $this->maxrecords, $tsearch->url());
     }
 }