";
+ $coursetagdivs .= '"f_commtags", ';
+ }
+ // Tidy up the end of a javascript array
+ $coursetagdivs = rtrim($coursetagdivs, ', ');
+
+ // Add the divs (containing the tags) to the block's content
+ $this->content->text = "
+
+ ";
+ if ($alltags) $this->content->text .= $alltagscontent;
+ if ($mytags) $this->content->text .= $mytagscontent;
+ if ($officialtags) $this->content->text .= $officialtagscontent;
+ if ($coursetags) $this->content->text .= $coursetagscontent;
+ if ($commtags) $this->content->text .= $commtagscontent;
+
+ // add the input form section (allowing a user to tag the current course) and navigation, or loggin message
+ if ($loggedin) {
+ // only show the input form on course pages for those allowed (or not barred)
+ if ($coursepage && $canedit) {
+ $this->content->footer .= coursetag_get_jscript();
+ $this->content->footer .= "
+ ";
+ // add the edit link
+ $this->content->footer .= "
+ ".get_string('edittags', $tagslang)."";
+ }
+
+ // Navigation elements at the bottom of the block
+ // show the alternative displays options if available
+ if ($mytags or $officialtags or $commtags or $coursetags) {
+ $this->content->footer .= "";
+ }
+ if ($mytags) {
+ $this->content->footer .= "
+
+ ".get_string('mytags2', $tagslang)." |";
+ }
+ if ($alltags and ($mytags or $officialtags or $commtags or $coursetags)) {
+ $this->content->footer .= "
+
+ ".get_string('alltags1', $tagslang)." |";
+ }
+ if ($officialtags) {
+ $this->content->footer .= "
+
+ ".get_string('officialtags1', $tagslang)." |";
+ }
+ if ($commtags) {
+ $this->content->footer .= "
+
+ ".get_string('communitytags1', $tagslang)." |";
+ }
+ if ($coursetags) {
+ $this->content->footer .= "
+
+ ".get_string('coursetags1', $tagslang)." |";
+ }
+ $this->content->footer = rtrim($this->content->footer, '|');
+ $this->content->footer .= '
';
+ } else {
+ //if not logged in
+ $this->content->footer = "".get_string('please', $tagslang)."
+ ".get_string('login', $tagslang)."
+ ".get_string('tagunits', $tagslang).'';
+ }
+ } // end of SHOWCOURSETAGS section
return $this->content;
}
@@ -81,6 +330,22 @@
notice(get_string('blockconfigbad'), str_replace('blockaction=', 'dummy=', qualified_me()));
}
}
-}
+
+ /*
+ * function removed unit rsslib supports dc/cc
+ */
+ /*
+ function cron() {
+ if (SHOWCOURSETAGS) {
+ global $CFG;
+ require_once($CFG->dirroot.'/blocks/tags/coursetagslib.php');
+ return coursetag_rss_feeds();
+ } else {
+ return TRUE;
+ }
+ }
+ */
+
+}
?>
Index: tag/lib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/tag/lib.php,v
retrieving revision 1.46
diff -u -r1.46 lib.php
--- tag/lib.php 1 Nov 2007 12:32:59 -0000 1.46
+++ tag/lib.php 10 Jan 2008 08:37:44 -0000
@@ -364,9 +364,13 @@
* @param string $item_id id of the item to be tagged
* @param string $tag_names_or_ids_csv comma separated tag names (can be unormalized) or ids of existing tags
* @param string $tag_type type of the tags that are beeing added (optional, default value is "default")
+ *
+ * coursetag addition
+ * the addition of userid here allows a tag to be associated with both an item and a user
+ * @param int $userid userid of creator of this tag instance or 0
*/
-function tag_an_item($item_type, $item_id, $tag_names_or_ids_csv, $tag_type="default") {
+function tag_an_item($item_type, $item_id, $tag_names_or_ids_csv, $tag_type="default", $userid=0) {
global $CFG;
//convert any tag ids passed to their corresponding tag names
@@ -400,6 +404,7 @@
$tag_instance = new StdClass;
$tag_instance->itemtype = $item_type;
$tag_instance->itemid = $item_id;
+ $tag_instance->tiuserid = $userid;
//create tag instances
@@ -408,7 +413,9 @@
$tag_instance->tagid = $tag_id;
$tag_instance->ordering = $ordering[$tag_normalized_name];
$tag_instance->timemodified = time();
- $tag_instance_exists = get_record('tag_instance', 'tagid', $tag_id, 'itemtype', $item_type, 'itemid', $item_id);
+ //$tag_instance_exists = get_record('tag_instance', 'tagid', $tag_id, 'itemtype', $item_type, 'itemid', $item_id);
+ $query = "tagid = $tag_id AND itemtype = '$item_type' AND itemid = $item_id AND tiuserid = $userid";
+ $tag_instance_exists = get_record_select('tag_instance', $query);
if (!$tag_instance_exists) {
insert_record('tag_instance',$tag_instance);
@@ -842,9 +849,10 @@
// query that counts how many times any tag appears together in items
// with the tag passed as argument ($tag_id)
- $query = "SELECT tb.tagid , COUNT(*) nr
+ $query = "SELECT tb.tagid , COUNT(*) as nr
FROM {$CFG->prefix}tag_instance ta
- INNER JOIN {$CFG->prefix}tag_instance tb ON ta.itemid = tb.itemid
+ INNER JOIN {$CFG->prefix}tag_instance tb
+ ON ta.itemid = tb.itemid
WHERE ta.tagid = {$tag_id}
GROUP BY tb.tagid
ORDER BY nr DESC";
@@ -900,18 +908,17 @@
// then this tag_instance is an orphan and it will be removed.
foreach ($items_types as $type) {
- $query = "
- {$CFG->prefix}tag_instance.id
- IN
- ( SELECT sq1.id
- FROM
- (SELECT sq2.*
+ $query = "{$CFG->prefix}tag_instance.id
+ IN (
+ SELECT sq1.id
+ FROM (
+ SELECT sq2.*
FROM {$CFG->prefix}tag_instance sq2
- LEFT JOIN {$CFG->prefix}{$type->itemtype} item
+ LEFT JOIN {$CFG->prefix}tag item
ON sq2.itemid = item.id
WHERE item.id IS NULL
- AND sq2.itemtype = '{$type->itemtype}')
- sq1
+ AND sq2.itemtype = '{$type->itemtype}'
+ ) sq1
) ";
delete_records_select('tag_instance', $query);
@@ -1129,10 +1136,12 @@
function tag_cron(){
+ mtrace('Start of tag cron - tag instance table cleanup');
tag_instance_table_cleanup();
if ($tags = get_all_tags('*')) {
+ mtrace(' Preparing to update correlated tags cache');
foreach ($tags as $tag){
cache_correlated_tags($tag->id);
}
@@ -1510,7 +1519,13 @@
$size = ceil($size);
$style = 'style="font-size: '.$size.'%"';
+
+ if ($tag->count > 1) {
$title = 'title="'.s(get_string('thingstaggedwith','tag', $tag)).'"';
+ } else {
+ $title = 'title="'.s(get_string('thingtaggedwith','tag', $tag)).'"';
+ }
+
$href = 'href="'.$CFG->wwwroot.'/tag/index.php?id='.$tag->id.'"';
//highlight tags that have been flagged as inappropriate for those who can manage them
Index: tag/index.php
===================================================================
RCS file: /cvsroot/moodle/moodle/tag/index.php,v
retrieving revision 1.16
diff -u -r1.16 index.php
--- tag/index.php 31 Aug 2007 05:46:33 -0000 1.16
+++ tag/index.php 10 Jan 2008 08:37:44 -0000
@@ -94,7 +94,7 @@
// Print last 10 blogs
-// I was not able to use get_items_tagged_with() because it automatically
+// I was not able to use get_items_tagged_with() because it automatically
// tries to join on 'blog' table, since the itemtype is 'blog'. However blogs
// uses the post table so this would not really work. - Yu 29/8/07
if ($blogs = blog_fetch_entries('', 10, 0, 'site', '', $tag->id)) {
@@ -114,7 +114,7 @@
echo '';
echo format_string($blog->subject);
echo '';
- echo ' - ';
+ echo ' - ';
echo '';
echo fullname($blog);
echo '';
@@ -129,6 +129,27 @@
}
+// Display courses tagged with the tag
+require_once($CFG->dirroot.'/blocks/tags/coursetagslib.php');
+if ($courses = coursetag_get_tagged_courses($tag->id)) {
+
+ $totalcount = count( $courses );
+
+ print_box_start('generalbox', 'tag-blogs');
+
+ print_heading('Units tagged with "'.$tagname.'": '.$totalcount, '', 3);
+
+ foreach ($courses as $course) {
+ //echo '
Index: lib/db/upgrade.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lib/db/upgrade.php,v
retrieving revision 1.172
diff -u -r1.172 upgrade.php
--- lib/db/upgrade.php 23 Dec 2007 20:01:14 -0000 1.172
+++ lib/db/upgrade.php 10 Jan 2008 08:37:44 -0000
@@ -2312,7 +2312,7 @@
$table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id'));
/*
- * Note: mysql can not create indexes on text fields larger than 333 chars!
+ * Note: mysql can not create indexes on text fields larger than 333 chars!
*/
/// Adding indexes to table cache_flags
@@ -2357,7 +2357,7 @@
if (index_exists($table, $index)) {
$result = $result && drop_index($table, $index);
}
-
+
$table = new XMLDBTable('cache_flags');
$index = new XMLDBIndex('flagtype');
$index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('flagtype'));
@@ -2519,7 +2519,7 @@
FROM {$CFG->prefix}user_lastaccess
WHERE NOT EXISTS (SELECT 'x'
FROM {$CFG->prefix}course c
- WHERE c.id = {$CFG->prefix}user_lastaccess.courseid)";
+ WHERE c.id = {$CFG->prefix}user_lastaccess.courseid)";
execute_sql($sql);
upgrade_main_savepoint($result, 2007100902);
@@ -2542,16 +2542,16 @@
upgrade_main_savepoint($result, 2007100903);
}
-
+
if ($result && $oldversion < 2007101500 && !file_exists($CFG->dataroot . '/user')) {
// Get list of users by browsing moodledata/user
$oldusersdir = $CFG->dataroot . '/users';
$folders = get_directory_list($oldusersdir, '', false, true, false);
-
+
foreach ($folders as $userid) {
$olddir = $oldusersdir . '/' . $userid;
$files = get_directory_list($olddir);
-
+
if (empty($files)) {
continue;
}
@@ -2578,7 +2578,7 @@
$readmefilename = $oldusersdir . '/README.txt';
if ($handle = fopen($readmefilename, 'w+b')) {
if (!fwrite($handle, get_string('olduserdirectory'))) {
- // Could not write to the readme file. No cause for huge concern
+ // Could not write to the readme file. No cause for huge concern
notify("Could not write to the README.txt file in $readmefilename.");
}
fclose($handle);
@@ -2586,22 +2586,22 @@
// Could not create the readme file. No cause for huge concern
notify("Could not create the README.txt file in $readmefilename.");
}
- }
+ }
if ($result && $oldversion < 2007101502) {
/// try to remove duplicate entries
-
+
$SQL = "SELECT userid, itemid, COUNT(*)
FROM {$CFG->prefix}grade_grades
GROUP BY userid, itemid
HAVING COUNT( * ) >1";
// duplicates found
-
+
if ($rs = get_recordset_sql($SQL)) {
if ($rs && $rs->RecordCount() > 0) {
while ($dup = rs_fetch_next_record($rs)) {
- if ($thisdups = get_records_sql("SELECT id FROM {$CFG->prefix}grade_grades
+ if ($thisdups = get_records_sql("SELECT id FROM {$CFG->prefix}grade_grades
WHERE itemid = $dup->itemid AND userid = $dup->userid
ORDER BY timemodified DESC")) {
@@ -2629,7 +2629,7 @@
/// Main savepoint reached
upgrade_main_savepoint($result, 2007101502);
- }
+ }
if ($result && $oldversion < 2007101503) {
// Update courses that used weekscss to weeks
@@ -2664,13 +2664,36 @@
$sql = "DELETE
FROM {$CFG->prefix}context
WHERE contextlevel=20";
-
+
execute_sql($sql);
/// Main savepoint reached
upgrade_main_savepoint($result, 2007101506);
}
+ if ($result && $oldversion < 2007101507) {
+
+ // table to be modified
+ $table = new XMLDBTable('tag_instance');
+ // add field
+ $field = new XMLDBField('tiuserid');
+ if (!field_exists($table, $field)) {
+ $field->setAttributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, 0, 'itemid');
+ $result = $result && add_field($table, $field);
+ }
+ // modify index
+ $index = new XMLDBIndex('itemtype-itemid-tagid');
+ $index->setAttributes(XMLDB_INDEX_UNIQUE, array('itemtype', 'itemid', 'tagid'));
+ drop_index($table, $index);
+ $index = new XMLDBIndex('itemtype-itemid-tagid-tiuserid');
+ $index->setAttributes(XMLDB_INDEX_UNIQUE, array('itemtype', 'itemid', 'tagid', 'tiuserid'));
+ drop_index($table, $index); //should not be required, but better safe than sorry
+ $result = $result && add_index($table, $index);
+
+ /// Main savepoint reached
+ upgrade_main_savepoint($result, 2007101507);
+ }
+
return $result;
}
Index: version.php
===================================================================
RCS file: /cvsroot/moodle/moodle/version.php,v
retrieving revision 1.573
diff -u -r1.573 version.php
--- version.php 23 Dec 2007 20:01:14 -0000 1.573
+++ version.php 10 Jan 2008 08:37:39 -0000
@@ -6,7 +6,7 @@
// This is compared against the values stored in the database to determine
// whether upgrades should be performed (see lib/db/*.php)
- $version = 2007101506; // YYYYMMDD = date
+ $version = 2007101507; // YYYYMMDD = date
// XY = increments within a single day
$release = '2.0 dev'; // Human-friendly version name
Index: lib/moodlelib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lib/moodlelib.php,v
retrieving revision 1.985
diff -u -r1.985 moodlelib.php
--- lib/moodlelib.php 1 Jan 2008 17:23:05 -0000 1.985
+++ lib/moodlelib.php 10 Jan 2008 08:37:42 -0000
@@ -1875,12 +1875,12 @@
// Fetch the course context, and prefetch its child contexts
if (!isset($COURSE->context)) {
if ( ! $COURSE->context = get_context_instance(CONTEXT_COURSE, $COURSE->id) ) {
- print_error('nocontext');
+ print_error('nocontext');
}
}
if ($COURSE->id == SITEID) {
/// Eliminate hidden site activities straight away
- if (!empty($cm) && !$cm->visible
+ if (!empty($cm) && !$cm->visible
&& !has_capability('moodle/course:viewhiddenactivities', $COURSE->context)) {
redirect($CFG->wwwroot, get_string('activityiscurrentlyhidden'));
}
@@ -1892,7 +1892,7 @@
if (empty($USER->access['rsw'][$COURSE->context->path])) {
//
// Spaghetti logic construct
- //
+ //
// - able to view course?
// - able to view category?
// => if either is missing, course is hidden from this user
@@ -1901,14 +1901,14 @@
// more costly checks last...
//
if (! (($COURSE->visible || has_capability('moodle/course:viewhiddencourses', $COURSE->context))
- && (course_parent_visible($COURSE)) || has_capability('moodle/course:viewhiddencourses',
+ && (course_parent_visible($COURSE)) || has_capability('moodle/course:viewhiddencourses',
get_context_instance(CONTEXT_COURSECAT,
$COURSE->category)))) {
print_header_simple();
notice(get_string('coursehidden'), $CFG->wwwroot .'/');
}
- }
-
+ }
+
/// Non-guests who don't currently have access, check if they can be allowed in as a guest
if ($USER->username != 'guest' and !has_capability('moodle/course:view', $COURSE->context)) {
@@ -1923,7 +1923,7 @@
if (has_capability('moodle/legacy:guest', $COURSE->context, NULL, false)) {
switch ($COURSE->guest) { /// Check course policy about guest access
- case 1: /// Guests always allowed
+ case 1: /// Guests always allowed
if (!has_capability('moodle/course:view', $COURSE->context)) { // Prohibited by capability
print_header_simple();
notice(get_string('guestsnotallowed', '', format_string($COURSE->fullname)), "$CFG->wwwroot/login/index.php");
@@ -1971,7 +1971,7 @@
/// Make sure they can read this activity too, if specified
- if (!empty($cm) and !$cm->visible and !has_capability('moodle/course:viewhiddenactivities', $COURSE->context)) {
+ if (!empty($cm) and !$cm->visible and !has_capability('moodle/course:viewhiddenactivities', $COURSE->context)) {
redirect($CFG->wwwroot.'/course/view.php?id='.$cm->course, get_string('activityiscurrentlyhidden'));
}
return; // User is allowed to see this course
@@ -3031,7 +3031,7 @@
* Call to complete the user login process after authenticate_user_login()
* has succeeded. It will setup the $USER variable and other required bits
* and pieces.
- *
+ *
* NOTE:
* - It will NOT log anything -- up to the caller to decide what to log.
*
@@ -3043,7 +3043,7 @@
*/
function complete_user_login($user) {
global $CFG, $USER;
-
+
$USER = $user; // should not be needed, but cover for legacy code
update_user_login_times();
@@ -3542,6 +3542,13 @@
/// Delete questions and question categories
question_delete_course($course, $showfeedback);
+/// Delete course tags
+ require_once($CFG->dirroot.'/blocks/tags/coursetagslib.php');
+ coursetag_delete_course_tags($course->id);
+ if ($showfeedback) {
+ notify("$strdeleted course tags");
+ }
+
return $result;
}
@@ -4294,7 +4301,7 @@
/// If you don't want a welcome message sent, then make the message string blank.
if (!empty($message)) {
$subject = get_string('welcometocourse', '', format_string($course->fullname));
-
+
if (! $teacher = get_teacher($course->id)) {
$teacher = get_admin();
}
@@ -4349,7 +4356,7 @@
// Generate a two-level path for the userid. First level groups them by slices of 1000 users, second level is userid
$level1 = floor($userid / 1000) * 1000;
-
+
$userdir = "user/$level1/$userid";
if ($test) {
return $CFG->dataroot . '/' . $userdir;
@@ -4363,20 +4370,20 @@
*
* @param bool $only_non_empty Only return directories that contain files
* @param bool $legacy Search for user directories in legacy location (dataroot/users/userid) instead of (dataroot/user/section/userid)
- * @return array An associative array: userid=>array(basedir => $basedir, userfolder => $userfolder)
+ * @return array An associative array: userid=>array(basedir => $basedir, userfolder => $userfolder)
*/
function get_user_directories($only_non_empty=true, $legacy=false) {
global $CFG;
$rootdir = $CFG->dataroot."/user";
-
+
if ($legacy) {
- $rootdir = $CFG->dataroot."/users";
+ $rootdir = $CFG->dataroot."/users";
}
$dirlist = array();
- //Check if directory exists
- if (check_dir_exists($rootdir, true)) {
+ //Check if directory exists
+ if (check_dir_exists($rootdir, true)) {
if ($legacy) {
if ($userlist = get_directory_list($rootdir, '', true, true, false)) {
foreach ($userlist as $userid) {
@@ -4384,7 +4391,7 @@
}
} else {
notify("no directories found under $rootdir");
- }
+ }
} else {
if ($grouplist =get_directory_list($rootdir, '', true, true, false)) { // directories will be in the form 0, 1000, 2000 etc...
foreach ($grouplist as $group) {
@@ -4394,7 +4401,7 @@
}
}
}
- }
+ }
}
} else {
notify("$rootdir does not exist!");
@@ -6363,7 +6370,7 @@
* @param string $text - text to be shortened
* @param int $ideal - ideal string length
* @param boolean $exact if false, $text will not be cut mid-word
- * @return string $truncate - shortened string
+ * @return string $truncate - shortened string
*/
function shorten_text($text, $ideal=30, $exact = false) {
@@ -6375,7 +6382,7 @@
if (strlen(preg_replace('/<.*?>/', '', $text)) <= $ideal) {
return $text;
}
-
+
// splits all html-tags to scanable lines
preg_match_all('/(<.+?>)?([^<>]*)/s', $text, $lines, PREG_SET_ORDER);
@@ -6431,7 +6438,7 @@
$truncate .= $line_matchings[2];
$total_length += $content_length;
}
-
+
// if the maximum length is reached, get off the loop
if($total_length >= $ideal) {
break;
@@ -6452,7 +6459,7 @@
}
}
}
-
+
if (isset($breakpos)) {
// ...and cut the text in this position
$truncate = substr($truncate, 0, $breakpos);
Index: lang/en_utf8/block_tags.php
===================================================================
RCS file: lang/en_utf8/block_tags.php
diff -N lang/en_utf8/block_tags.php
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ lang/en_utf8/block_tags.php 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,66 @@
+
Index: lang/en_utf8/help/block_tags/deletetags.html
===================================================================
RCS file: lang/en_utf8/help/block_tags/deletetags.html
diff -N lang/en_utf8/help/block_tags/deletetags.html
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ lang/en_utf8/help/block_tags/deletetags.html 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,9 @@
+
Deleting a tag for a course
+
+
You will only be able to delete a tag entry that you have previously created.
+This allows you to tidy up those mis-spelled, or out-dated tags. Please note that
+deletion will only delete the tag if no other user has tagged something else with it,
+otherwise deletion will just delete your association of that tag for the course.
+
+
Deleting is done by highlighting the tag you wish to delete under 'Select...',
+then clicking the 'Submit' button below.
A tag is a shortcut or way of navigating to your favourite things.
+
+
Not only can you tag courses, but you may also tag your blogs, or even your own profile.
+
+
Clicking on a tag will take you to a page listing all the things associated with that tag.
+If the tag is a popular one you will be able to see what other things other users have associated
+with that tag.
+
+
You may add as many tags as you like. While it is recommended to only add one tag at a time,
+more tags could be entered on one occasion by seperating the tags with a comma.
+As you are adding a tag you may notice a word appearing in the background where you are typing.
+If this word is what you want as your tag then you can click on the little
+arrow next to the entry box to save typing the that word (and don't forget to click submit to save).
+
+
Tags must be more than one character and may be up to 50 characters long.
+Please note that while extended characters are allowed (e.g. French acute
+accented characters or Chinese characters), special characters will be
+stripped (e.g. "',\,_,<,-,~,?").
+Also note that tags cannot be pure integers or float number (e.g. 1 or 1.11)
+but number and letter combinations are fine (e.g. 1a).
+Finally, commas cannot be used in tag names, as these are separators between tags entered.
+
+
Don't forget to click the 'Submit' button below to save your new tag.
Index: blocks/tags/coursetagslib.php
===================================================================
RCS file: blocks/tags/coursetagslib.php
diff -N blocks/tags/coursetagslib.php
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ blocks/tags/coursetagslib.php 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,447 @@
+dirroot.'/tag/lib.php';
+
+/**
+ * Returns an ordered array of tags associated with visible courses
+ * (boosted replacement of get_all_tags() allowing association with user and tagtype).
+ *
+ * @uses $CFG
+ * @param int $courseid, a 0 will return all distinct tags for visible courses
+ * @param int $userid optional the user id, a default of 0 will return all users tags for the course
+ * @param string $tagtype optional 'official' or 'personal', default returns both tag types
+ * @param int $numtags optional number of tags to display, default of 20 is set in the block, 0 returns all
+ * @param string $sort optional selected sorting, default is alpha sort (name) also timemodified or popularity
+ * @param int $timewithin optional limit to age of tags to be displayed, default returns all
+ * @return array
+ */
+function coursetag_get_tags($courseid, $userid=0, $tagtype='', $numtags=0, $sort='name', $timewithin=10) {
+
+ global $CFG;
+
+ // get visible course ids
+ if ($courseid === 0) {
+ $courselist = '(';
+ if ($courses = get_records_select('course', 'visible=1 AND category>0', '', 'id')) {
+ foreach ($courses as $key => $value) {
+ $courselist .= "$key, ";
+ }
+ $courselist = rtrim($courselist, ', ');
+ $courselist .= ')';
+ } else {
+ $courselist = '';
+ }
+ }
+
+ // get tags from the db ordered by highest count first
+ $sql = "SELECT id as key, name, id, tagtype, rawname, f.timemodified, flag, count
+ FROM {$CFG->prefix}tag t,
+ (SELECT tagid, MAX(timemodified) as timemodified, COUNT(id) as count
+ FROM {$CFG->prefix}tag_instance
+ WHERE itemtype = 'course'
+ AND timemodified > $timewithin ";
+ if ($courseid > 0) {
+ $sql .= "AND itemid = $courseid ";
+ } else {
+ if ($courselist) {
+ $sql .= "AND itemid IN $courselist ";
+ }
+ }
+ if ($userid > 0) $sql .= "AND tiuserid = $userid ";
+ $sql .= "GROUP BY tagid) f
+ WHERE t.id = f.tagid ";
+ if ($tagtype == 'official') $sql .= "AND tagtype = '$tagtype' ";
+ $sql .= "ORDER BY count DESC, name ASC";
+
+ // limit the number of tags for output
+ if ($numtags == 0) {
+ $tags = get_records_sql($sql);
+ } else {
+ $tags = get_records_sql($sql, 0, $numtags);
+ }
+
+ // prepare the return
+ $return = array();
+ if ($tags) {
+ // sort the tag display order
+ if ($sort != 'popularity') {
+ $CFG->tagsort = $sort;
+ usort($tags, "coursetag_sort");
+ }
+ // avoid print_tag_cloud()'s ksort upsetting ordering by setting the key here
+ foreach ($tags as $value) {
+ $return[] = $value;
+ }
+ }
+
+ return $return;
+
+}
+
+/**
+ * Returns an ordered array of tags
+ * (replaces popular_tags_count() allowing sorting).
+ *
+ * @uses $CFG
+ * @param string $sort optional selected sorting, default is alpha sort (name) also timemodified or popularity
+ * @param int $numtags optional number of tags to display, default of 20 is set in the block, 0 returns all
+ * @return array
+ */
+function coursetag_get_all_tags($sort='name', $numtags=0) {
+
+ global $CFG;
+
+ $sql = "SELECT id as key, name, id, tagtype, rawname, f.timemodified, flag, count
+ FROM {$CFG->prefix}tag t,
+ (SELECT tagid, MAX(timemodified) as timemodified, COUNT(id) as count
+ FROM {$CFG->prefix}tag_instance
+ GROUP BY tagid) f
+ WHERE t.id = f.tagid
+ ORDER BY count DESC, name ASC";
+
+ if ($numtags == 0) {
+ $tags = get_records_sql($sql);
+ } else {
+ $tags = get_records_sql($sql, 0, $numtags);
+ }
+
+ $return = array();
+ if ($tags) {
+ if ($sort != 'popularity') {
+ $CFG->tagsort = $sort;
+ usort($tags, "coursetag_sort");
+ }
+ foreach ($tags as $value) {
+ $return[] = $value;
+ }
+ }
+
+ return $return;
+
+}
+
+/**
+ * Callback function for coursetag_get_tags() and coursetag_get_tags() only
+ * @uses $CFG
+ */
+function coursetag_sort($a, $b) {
+ // originally from block_blog_tags
+ global $CFG;
+
+ // set up the variable $tagsort as either 'name' or 'timemodified' only, 'popularity' does not need sorting
+ if (empty($CFG->tagsort)) {
+ $tagsort = 'name';
+ } else {
+ $tagsort = $CFG->tagsort;
+ }
+
+ if (is_numeric($a->$tagsort)) {
+ return ($a->$tagsort == $b->$tagsort) ? 0 : ($a->$tagsort < $b->$tagsort) ? 1 : -1;
+ } elseif (is_string($a->$tagsort)) {
+ return strcmp($a->$tagsort, $b->$tagsort);
+ } else {
+ return 0;
+ }
+}
+
+/**
+ * Return a javascript block for use in tags block and supporting pages
+ * @uses $CFG
+ */
+function coursetag_get_jscript() {
+
+ global $CFG;
+
+ $coursetags = get_all_tags('*', $sort='name ASC', $fields='name, id');
+ $a = 0;
+ $coursetagscript = '';
+ if (!empty($coursetags)) {
+ foreach ($coursetags as $key => $value) {
+ $coursetagscript .= "coursetag_tags[$a] = \"$key\"; ";
+ $a++;
+ }
+ }
+ $str = "";
+
+ return $str;
+
+}
+
+/**
+ * Returns all tags created by a user for a course
+ *
+ * @uses $CFG
+ * @param int $courseid
+ * @param int $userid
+ */
+function coursetag_get_records($courseid, $userid) {
+
+ global $CFG;
+
+ $sql = "SELECT t.id, name, rawname
+ FROM {$CFG->prefix}tag t, {$CFG->prefix}tag_instance ti
+ WHERE t.id = ti.tagid
+ AND t.tagtype = 'personal'
+ AND ti.tiuserid = '$userid'
+ AND ti.itemid = '$courseid'
+ ORDER by name ASC";
+ $return = get_records_sql($sql);
+
+ return $return;
+
+}
+
+/**
+ * Stores a tag for a course for a user
+ *
+ * @uses $CFG
+ * @param array $tags simple array of keywords to be stored
+ * @param integer $courseid
+ * @param integer $userid defaults to admin user
+ * @param string $tagtype official (default) or personal only
+ * @param string $myurl optional for logging creation of course tags
+ */
+function coursetag_store_keywords($tags, $courseid, $userid=3, $tagtype='official', $myurl='') {
+
+ global $CFG;
+
+ if (is_array($tags) and !empty($tags)) {
+ foreach($tags as $tag) {
+ // don't store non-existant tags
+ if (strlen($tag) > 0) {
+ tag_an_item('course', $courseid, $tag, $tagtype, $userid);
+ if ($tagtype == 'personal' and $myurl != '') {
+ // log the tagging request
+ add_to_log($courseid, 'coursetags', 'add', $myurl, 'Personal tag \''.$tag.'\'');
+ }
+ }
+ }
+ }
+
+}
+
+/**
+ * Deletes a personal tag for a user for a course.
+ *
+ * @uses $CFG
+ * @param int $tagid
+ * @param int $userid
+ * @param int $courseid
+ */
+function coursetag_delete_keyword($tagid, $userid, $courseid) {
+
+ global $CFG;
+
+ $sql = "SELECT COUNT(*)
+ FROM {$CFG->prefix}tag_instance
+ WHERE tagid = $tagid
+ AND tiuserid = $userid
+ AND itemtype = 'course'
+ AND itemid = $courseid";
+ if (count_records_sql($sql) == 1) {
+ $sql = "tagid = $tagid
+ AND tiuserid = $userid
+ AND itemtype = 'course'
+ AND itemid = $courseid";
+ delete_records_select('tag_instance', $sql);
+ // if there are no other instances of the tag then consider deleting the tag as well
+ if (!record_exists('tag_instance', 'tagid', $tagid)) {
+ // if the tag is a personal tag then delete it
+ if (record_exists('tag', 'id', $tagid, 'tagtype', 'personal')) {
+ delete_records('tag', 'id', $tagid, 'tagtype', 'personal');
+ }
+ }
+ } else {
+ error("Error deleting tag with id $tagid, please report to your system administrator.");
+ }
+
+}
+
+/**
+ * Function used only during the deletion of a course (lib/moodlelib.php)
+ *
+ * @param $courseid
+ */
+function coursetag_delete_course_tags($courseid) {
+ if ($tags = get_records_select('tag_instance', "itemtype='course' AND itemid=".$courseid)) {
+ foreach ($tags as $tag) {
+ //delete the course tag instance record
+ delete_records('tag_instance', 'tagid', $tag->tagid, 'itemtype', 'course', 'itemid', $courseid);
+ // delete tag if there are no other tag_instance entries now
+ if (!(record_exists('tag_instance', 'tagid', $tag->tagid))) {
+ delete_records('tag', 'id', $tag->tagid);
+ }
+ }
+ }
+}
+
+/**
+ * Get courses tagged with a tag
+ *
+ * @param $tagid
+ * @return array of course objects
+ */
+function coursetag_get_tagged_courses($tagid) {
+
+ $courses = array();
+ if ($crs = get_records_select('tag_instance', "tagid='$tagid' AND itemtype='course'", '', 'itemid')) {
+ foreach ($crs as $c) {
+ if (has_capability('moodle/course:view', get_context_instance(CONTEXT_COURSE, $c->itemid))) {
+ $course = get_record('course', 'id', $c->itemid);
+ $courses[$c->itemid] = $course;
+ }
+ }
+ }
+ return $courses;
+
+}
+
+/**
+ * Function called by cron to create/update users rss feeds
+ *
+ * @uses $CFG
+ * @return true
+ *
+ * Function removed.
+ * rsslib.php needs updating to accept dc/cc input before this can work (or modified).
+ */
+/*
+function coursetag_rss_feeds() {
+
+ global $CFG;
+ require_once($CFG->dirroot.'/lib/dmllib.php');
+ require_once($CFG->dirroot.'/lib/rsslib.php');
+
+ $status = true;
+ mtrace(' Preparing to update all user unit tags RSS feeds');
+ if (empty($CFG->enablerssfeeds)) {
+ mtrace(' RSS DISABLED (admin variables - enablerssfeeds)');
+ } else {
+
+ // Load all the categories for use later on
+ $categories = get_records('course_categories');
+
+ // get list of users who have tagged a unit
+ $sql = "
+ SELECT DISTINCT u.id as userid, u.username, u.firstname, u.lastname, u.email
+ FROM {$CFG->prefix}user u, {$CFG->prefix}course c, {$CFG->prefix}tag_instance cti, {$CFG->prefix}tag t
+ WHERE c.id = cti.itemid
+ AND u.id = cti.tiuserid
+ AND t.id = cti.tagid
+ AND t.tagtype = 'personal'
+ AND u.confirmed = 1
+ AND u.deleted = 0
+ ORDER BY userid";
+ if ($users = get_records_sql($sql)) {
+
+ $items = array(); //contains rss data items for each user
+ foreach ($users as $user) {
+
+ // loop through each user, getting the data (tags for courses)
+ $sql = "
+ SELECT cti.id, c.id as courseid, c.fullname, c.shortname, c.category, t.rawname, cti.timemodified
+ FROM {$CFG->prefix}course c, {$CFG->prefix}tag_instance cti, {$CFG->prefix}tag t
+ WHERE c.id = cti.itemid
+ AND cti.tiuserid = {$user->userid}
+ AND cti.tagid = t.id
+ AND t.tagtype = 'personal'
+ ORDER BY courseid";
+ if ($usertags = get_records_sql($sql)) {
+ $latest_date = 0; //latest date any tag was created by a user
+ $c = 0; //course identifier
+
+ foreach ($usertags as $usertag) {
+ if ($usertag->courseid != $c) {
+ $c = $usertag->courseid;
+ $items[$c] = new stdClass();
+ $items[$c]->title = $usertag->fullname . '(' . $usertag->shortname . ')';
+ $items[$c]->link = $CFG->wwwroot . '/course/view.php?name=' . $usertag->shortname;
+ $items[$c]->description = ''; //needs to be blank
+ $items[$c]->category = $categories[$usertag->category]->name;
+ $items[$c]->subject[] = $usertag->rawname;
+ $items[$c]->pubdate = $usertag->timemodified;
+ $items[$c]->tag = true;
+ } else {
+ $items[$c]->subject[] .= $usertag->rawname;
+ }
+ // Check and set the latest modified date.
+ $latest_date = $usertag->timemodified > $latest_date ? $usertag->timemodified : $latest_date;
+ }
+
+ // Setup some vars for use while creating the file
+ $path = $CFG->dataroot.'/1/usertagsrss/'.$user->userid;
+ $file_name = 'user_unit_tags_rss.xml';
+ $title = 'The OpenLearn Unit Tags RSS Feed for user: '.ucwords(strtolower($user->firstname.' '.$user->lastname));
+ $desc = 'This RSS feed was automatically generated by OpenLearn folksonomies and contains user generated tags for units.';
+ // check that the path exists
+ if (!file_exists($path)) {
+ mtrace(' Creating folder '.$path);
+ check_dir_exists($path, TRUE, TRUE);
+ }
+
+ // create or update the feed for the user
+ // this functionality can be copied entirely once rsslib is adjusted
+ require_once($CFG->dirroot.'/local/ocilib.php');
+ oci_create_rss_feed( $path, $file_name, $latest_date, $items, $title, $desc, true);
+ }
+ }
+ }
+ }
+
+ return $status;
+}
+ */
+
+/**
+ * Get official keywords for the in header.html
+ * use: echo '';
+ * @uses $CFG
+ * @param int $courseid
+ * @return string
+ *
+ * Function removed
+ * This function is potentially useful to anyone wanting to improve search results for course pages.
+ * The idea is to add official (not personal ones, so users cannot delete) tags to all
+ * courses (facility not added yet) which wil be automatically added to the page to boost
+ * search engine specificity/ratings.
+ */
+/*
+function coursetag_get_official_keywords($courseid, $asarray=false) {
+ global $CFG;
+ $returnstr = '';
+ $sql = "SELECT t.id, name, rawname
+ FROM {$CFG->prefix}tag t, {$CFG->prefix}tag_instance ti
+ WHERE ti.itemid = $courseid
+ AND ti.itemtype = 'course'
+ AND t.tagtype = 'official'
+ AND ti.tagid = t.id
+ ORDER BY name ASC";
+ if ($tags = get_records_sql($sql)) {
+ if ($asarray) {
+ return $tags;
+ }
+ foreach ($tags as $tag) {
+ if( empty($CFG->keeptagnamecase) ) {
+ $textlib = textlib_get_instance();
+ $name = $textlib->strtotitle($tag->name);
+ } else {
+ $name = $tag->rawname;
+ }
+ $returnstr .= $name.', ';
+ }
+ $returnstr = rtrim($returnstr, ', ');
+ }
+ return $returnstr;
+}
+*/
+
+?>
Index: blocks/tags/coursetags_edit.php
===================================================================
RCS file: blocks/tags/coursetags_edit.php
diff -N blocks/tags/coursetags_edit.php
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ blocks/tags/coursetags_edit.php 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,165 @@
+dirroot.'/blocks/tags/coursetagslib.php');
+require_once($CFG->dirroot.'/tag/lib.php');
+
+$courseid = optional_param('courseid', 1, PARAM_INT);
+$keyword = optional_param('coursetag_new_tag', '', PARAM_TEXT);
+$deltag = optional_param('del_tag', 0, PARAM_INT);
+
+if ($courseid > 0) {
+ if (! ($COURSE = get_record('course', 'id', $courseid)) ) {
+ error('Invalid course id');
+ }
+} else {
+ error('Invalid course id');
+}
+
+// Permissions
+$sitecontext = get_context_instance(CONTEXT_SYSTEM, SITEID);
+$isguest = has_capability('moodle/legacy:guest', $sitecontext, $USER->id, false);
+$loggedin = isloggedin() && !$isguest;
+$canedit = has_capability('moodle/tag:create', $sitecontext);
+
+// Language strings
+$tagslang = 'block_tags';
+
+// Store data
+if ($data = data_submitted()) {
+ if (confirm_sesskey() and $courseid > 0 and $USER->id > 0 and $canedit) {
+ // store personal tag
+ if (trim($keyword)) {
+ //$keywords = folks_input_to_keywords($keyword);
+ $keywords = (array)$keyword;
+ try {
+ coursetag_store_keywords($keywords, $courseid, $USER->id, 'personal');
+ }
+ catch (Exception $e) {
+ error($e->getmessage());
+ }
+ }
+ // delete personal tag
+ if ($deltag > 0) {
+ coursetag_delete_keyword($deltag, $USER->id, $courseid);
+ }
+ }
+}
+
+// The title and breadcrumb
+$title = get_string('edittitle', $tagslang);
+$nav = build_navigation(array(array('name' => $title, 'link' => null, 'type' => 'misc')));
+print_header_simple($title, '', $nav, '', '', false);
+
+// Tags for all - providing navigation to units
+print_heading($title, 'centre');
+
+// Personal tags section for logged in users
+if ($loggedin) {
+
+ $mytags = print_tag_cloud(coursetag_get_tags(0, $USER->id, 'personal'), false, 500, 100, true);
+ if ($mytags) {
+ $outstr = "
+
+ ".get_string('editmytags', $tagslang)."
+
+
+ $mytags
+
";
+ echo $outstr;
+ }
+
+ // Personal tag editing - not for site front page
+ if ($canedit and $courseid > 1) {
+ $title = get_string('editedit', $tagslang).' "'.$COURSE->fullname.' ('.$COURSE->shortname.')"';
+ print_heading($title);
+
+ // Deletion here is open to the registered users own tags for this course only
+ $selectoptions = "";
+ $coursetabs = '';
+ if ($options = coursetag_get_records($COURSE->id, $USER->id)) {
+ $coursetabs = '"';
+ foreach ($options as $value) {
+ $selectoptions .= "\n";
+ $coursetabs .= $value->rawname . ', ';
+ }
+ $coursetabs = rtrim($coursetabs, ', ');
+ $coursetabs .= '"';
+ }
+
+ // Print course tags
+ $outstr = '
';
+ echo $outstr;
+
+ // Getting deletions and additions to personal tags for a unit
+ $outstr = "
+ ";
+ $outstr .= coursetag_get_jscript();
+ $outstr .= "
+ ";
+ echo $outstr;
+ }
+
+}
+
+print_footer();
+?>
Index: lang/en_utf8/help/block_tags/usingtags.html
===================================================================
RCS file: lang/en_utf8/help/block_tags/usingtags.html
diff -N lang/en_utf8/help/block_tags/usingtags.html
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ lang/en_utf8/help/block_tags/usingtags.html 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,21 @@
+
Using course tagging
+
+
A note about the tag count. Hovering the mouse over a tag will reveal a tag count message
+like '2 things tagged with ...'.
+This count (number) will vary depending on where the tag is being displayed at the time.
+
+
The 'More tags' page (and the tags block) can display several different selections of tags
+- for instance 'all tags' or 'my tags'.
+The count displayed for a tag under 'all tags' may be different to the count for the same tag
+displayed under the 'my tags' or one of the other selections.
+This is because when 'all tags' is showing, all tags for courses, blogs and user profiles
+are displayed and counted.
+Where as when 'my tags' is showing, only your own tags for courses you have tagged
+are displayed and counted.
+So the count could be quite different for one tag under different sections.
+
+
Of course the size of the tag is also a clue to the count. The bigger the font size for the tag the
+more popular the tag is.
+
+
In fact it is easy to re-order the tags displayed by popularity, using the link provided.
+And the tags may be re-ordered alphabetically or in date of creation order as well. Try it.