### Eclipse Workspace Patch 1.0 #P core 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 20 Dec 2007 14:05:28 -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 20 Dec 2007 14:05:28 -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 '
'; + print_course($course); + //echo '
'; + print_spacer(5,5); + } + + print_box_end(); +} + + echo ''; Index: tag/search.php =================================================================== RCS file: /cvsroot/moodle/moodle/tag/search.php,v retrieving revision 1.5 diff -u -r1.5 search.php --- tag/search.php 28 Aug 2007 06:14:38 -0000 1.5 +++ tag/search.php 20 Dec 2007 14:05:28 -0000 @@ -22,6 +22,8 @@ $systemcontext = get_context_instance(CONTEXT_SYSTEM); if ( has_capability('moodle/tag:manage',$systemcontext) ) { $manage_link = "wwwroot}/tag/manage.php\">" . get_string('managetags', 'tag') . "" ; +} else { + $manage_link = NULL; } print_header_simple(get_string('tags', 'tag'), '', $navigation, '', '', '', $manage_link); Index: blocks/tags/block_tags.php =================================================================== RCS file: /cvsroot/moodle/moodle/blocks/tags/block_tags.php,v retrieving revision 1.3 diff -u -r1.3 block_tags.php --- blocks/tags/block_tags.php 16 Sep 2007 21:43:08 -0000 1.3 +++ blocks/tags/block_tags.php 20 Dec 2007 14:05:23 -0000 @@ -1,9 +1,18 @@ version = 2007082800; + $this->version = 2007120600; $this->title = get_string('blocktagstitle', 'tag'); + // the cron function goes through all users so only do daily + // remove until rsslib supports dc/cc + // $this->cron = 60*60*24; } function instance_allow_multiple() { @@ -61,7 +70,247 @@ require_once($CFG->dirroot.'/tag/lib.php'); - $this->content->text = print_tag_cloud(popular_tags_count($this->config->numberoftags), false, 170, 70, true); + if (!SHOWCOURSETAGS) { + + $this->content->text = print_tag_cloud(popular_tags_count($this->config->numberoftags), false, 170, 70, true); + + } else { + + require_once($CFG->dirroot.'/blocks/tags/coursetagslib.php'); + + // Permissions and page awareness + $sitecontext = get_context_instance(CONTEXT_SYSTEM, SITEID); + $isguest = has_capability('moodle/legacy:guest', $sitecontext, $USER->id, false); + $loggedin = isloggedin() && !$isguest; + $isadmin = has_capability('moodle/site:doanything', $sitecontext); + $coursepage = $canedit = false; + $coursepage = (isset($COURSE->id) && $COURSE->id != SITEID); + $mymoodlepage = strpos($_SERVER['PHP_SELF'], 'my') > 0 ? true : false; + $sitepage = (isset($COURSE->id) && $COURSE->id == SITEID && !$mymoodlepage); + $coursecontext = get_context_instance(CONTEXT_COURSE, $COURSE->id); + if ($coursepage) { + $canedit = has_capability('moodle/tag:create', $sitecontext); + } + + // Check rss feed - temporarily removed + //$rssfeed = ''; + //if (file_exists($CFG->dataroot.'/'.SITEID.'/usertagsrss/'.$USER->id.'/user_unit_tags_rss.xml')) { + // $rssfeed = '/file.php/'.SITEID.'/usertagsrss/'.$USER->id.'/user_unit_tags_rss.xml'; + //} + + // Language strings + $tagslang = 'block_tags'; + + // DB hits to get groups of marked up tags (if available) + //TODO check whether time limited personal tags are required + $numoftags = $this->config->numberoftags; + $sort = 'name'; + $alltags = $officialtags = $coursetags = $commtags = $mytags = $coursetagdivs = $courseflag = ''; + if ($sitepage or $coursepage) { + $alltags = print_tag_cloud(coursetag_get_all_tags($sort, $this->config->numberoftags), false, 170, 70, true); + $officialtags = print_tag_cloud(coursetag_get_tags(0, 0, 'official', $numoftags, $sort), false, 170, 70, true); + $commtags = print_tag_cloud(coursetag_get_tags(0, 0, 'personal', $numoftags, $sort), false, 170, 70, true); + if ($loggedin) { + $mytags = print_tag_cloud(coursetag_get_tags(0, $USER->id, 'personal', $numoftags, $sort), false, 170, 70, true); + } + } + if ($coursepage) { + $coursetags = print_tag_cloud(coursetag_get_tags($COURSE->id, 0, '', $numoftags, $sort), false, 170, 70, true); + if (!$coursetags) $coursetags = get_string('notagsyet', $tagslang); + $courseflag = '&courseid='.$COURSE->id; + } + if ($mymoodlepage) { + $mytags = print_tag_cloud(coursetag_get_tags(0, $USER->id, 'personal', $numoftags, $sort), false, 170, 70, true); + $officialtags = print_tag_cloud(coursetag_get_tags(0, 0, 'official', $numoftags, $sort), false, 170, 70, true); + $commtags = print_tag_cloud(coursetag_get_tags(0, 0, 'personal', $numoftags, $sort), false, 170, 70, true); + } + + // Prepare the divs and javascript that displays the groups of tags (and which is displayed first) + $moretags = $CFG->wwwroot.'/blocks/tags/coursetags_more.php'; + $moretagstitle = get_string('moretags', $tagslang); + $moretagsstring = get_string('more', $tagslang); + $displayblock = 'style="display:block"'; + $displaynone = 'style="display:none"'; //only one div created below will be displayed at a time + if ($alltags) { + if ($sitepage) { + $display = $displayblock; + } else { + $display = $displaynone; + } + $alltagscontent = " +
+ ".get_string('alltags', $tagslang)." + $alltags + +
"; + $coursetagdivs .= '"f_alltags", '; + } + if ($mytags) { + if ($mymoodlepage) { + $display = $displayblock; + } else { + $display = $displaynone; + } + $mytagscontent = " +
"; + /*if ($rssfeed) { // - temporarily removed + $mytagscontent .= link_to_popup_window( + $rssfeed, $name='popup', + 'User Unit Tags RSS My Unit Tags RSS', + $height=600, $width=800, + $title='My Unit Tags RSS', $options='menubar=1,scrollbars,resizable', $return=true).'
'; + }*/ + $mytagscontent .= get_string('mytags', $tagslang)." + $mytags + +
"; + $coursetagdivs .= '"f_mytags", '; + } + if ($officialtags) { + if ($mytags or $alltags) { + $display = $displaynone; + } else { + $display = $displayblock; + } + $officialtagscontent = " +
+ ".get_string('officialtags', $tagslang)." + $officialtags + +
"; + $coursetagdivs .= '"f_officialtags", '; + } + if ($coursetags) { + if ($coursepage) { + $display = $displayblock; + } else { + $display = $displaynone; + } + $coursetagscontent = " +
+
".get_string('coursetags', $tagslang)."
+ $coursetags + +
"; + $coursetagdivs .= '"f_coursetags", '; + } + if ($commtags) { + $commtagscontent = " +
+ ".get_string('communitytags', $tagslang)." + $commtags + +
"; + $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 .= "
+
+ + + ".get_string('tagthisunit', $tagslang)." +
+
+ +
+
+ +
+
+ + + +
+
+ "; + $this->content->footer .= helpbutton('addtags', 'adding tags', $tagslang, TRUE, FALSE, '', TRUE); + $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: course/lib.php =================================================================== RCS file: /cvsroot/moodle/moodle/course/lib.php,v retrieving revision 1.541 diff -u -r1.541 lib.php --- course/lib.php 27 Nov 2007 01:56:21 -0000 1.541 +++ course/lib.php 20 Dec 2007 14:05:24 -0000 @@ -13,11 +13,11 @@ define('COURSE_MAX_SUMMARIES_PER_PAGE', 10); // courses define('COURSE_MAX_COURSES_PER_DROPDOWN',1000); // max courses in log dropdown before switching to optional define('COURSE_MAX_USERS_PER_DROPDOWN',1000); // max users in log dropdown before switching to optional -define('FRONTPAGENEWS', 0); -define('FRONTPAGECOURSELIST', 1); -define('FRONTPAGECATEGORYNAMES', 2); -define('FRONTPAGETOPICONLY', 3); -define('FRONTPAGECATEGORYCOMBO', 4); +define('FRONTPAGENEWS', '0'); +define('FRONTPAGECOURSELIST', '1'); +define('FRONTPAGECATEGORYNAMES', '2'); +define('FRONTPAGETOPICONLY', '3'); +define('FRONTPAGECATEGORYCOMBO', '4'); define('FRONTPAGECOURSELIMIT', 200); // maximum number of courses displayed on the frontpage define('EXCELROWS', 65535); define('FIRSTUSEDEXCELROW', 3); @@ -260,6 +260,9 @@ case 'upload': return $url; break; + case 'coursetags': + return '/'.$url; + break; case 'library': case '': return '/'; @@ -280,11 +283,11 @@ // and so the next 86400 seconds worth of logs are printed. /// Setup for group handling. - - // TODO: I don't understand group/context/etc. enough to be able to do + + // TODO: I don't understand group/context/etc. enough to be able to do // something interesting with it here // What is the context of a remote course? - + /// If the group mode is separate, and this user does not have editing privileges, /// then only the user's group can be viewed. //if ($course->groupmode == SEPARATEGROUPS and !has_capability('moodle/course:managegroups', get_context_instance(CONTEXT_COURSE, $course->id))) { @@ -301,14 +304,14 @@ $qry = " SELECT l.*, - u.firstname, - u.lastname, + u.firstname, + u.lastname, u.picture FROM {$CFG->prefix}mnet_log l - LEFT JOIN + LEFT JOIN {$CFG->prefix}user u - ON + ON l.userid = u.id WHERE "; @@ -327,7 +330,7 @@ if ('site_errors' === $modid) { $where .= " AND\n ( l.action='error' OR l.action='infected' )"; } else if ($modid) { - //TODO: This assumes that modids are the same across sites... probably + //TODO: This assumes that modids are the same across sites... probably //not true $where .= " AND\n l.cmid = '$modid'"; } @@ -404,7 +407,7 @@ } } - + /// Getting all members of a group. if ($groupid and !$user) { if ($gusers = groups_get_members($groupid)) { @@ -489,7 +492,7 @@ if (empty($logs['logs'])) { $logs['logs'] = array(); } - + $row = 1; foreach ($logs['logs'] as $log) { @@ -550,16 +553,16 @@ function print_mnet_log($hostid, $course, $user=0, $date=0, $order="l.time ASC", $page=0, $perpage=100, $url="", $modname="", $modid=0, $modaction="", $groupid=0) { - + global $CFG; - + if (!$logs = build_mnet_logs_array($hostid, $course, $user, $date, $order, $page*$perpage, $perpage, $modname, $modid, $modaction, $groupid)) { notify("No logs found!"); print_footer($course); exit; } - + if ($course->id == SITEID) { $courses[0] = ''; if ($ccc = get_courses('all', 'c.id ASC', 'c.id,c.shortname,c.visible')) { @@ -568,7 +571,7 @@ } } } - + $totalcount = $logs['totalcount']; $count=0; $ldcache = array(); @@ -602,7 +605,7 @@ $row = 1; foreach ($logs['logs'] as $log) { - + $log->info = $log->coursename; $row = ($row + 1) % 2; @@ -621,7 +624,7 @@ } } - //Filter log->info + //Filter log->info $log->info = format_string($log->info); $log->url = strip_tags(urldecode($log->url)); // Some XSS protection @@ -1344,7 +1347,7 @@ /// Casting $course->modinfo to string prevents one notice when the field is null $modinfo = unserialize((string)$course->modinfo); - + $groupings = groups_get_all_groupings($course->id); //Acccessibility: replace table with list "; } } - + require_once("$CFG->dirroot/enrol/enrol.class.php"); $enrol = enrolment_factory::factory($course->enrol); echo $enrol->get_access_icons($course); @@ -1945,7 +1974,7 @@ } // MNET - if (!empty($rcourses)) { + if (!empty($rcourses)) { // at the IDP, we know of all the remote courses foreach ($rcourses as $course) { print_remote_course($course, "100%"); @@ -2037,8 +2066,8 @@ $linkcss.' href="'.$url.'">' . format_string($course->fullname) .'
' . format_string($course->hostname) . ' : ' - . format_string($course->cat_name) . ' : ' - . format_string($course->shortname). ''; + . format_string($course->cat_name) . ' : ' + . format_string($course->shortname). ''; echo '
'; $options = NULL; $options->noclean = true; @@ -2155,7 +2184,7 @@ } function set_coursemodule_idnumber($id, $idnumber) { - return set_field("course_modules", "idnumber", $idnumber, "id", $id); + return set_field("course_modules", "idnumber", $idnumber, "id", $id); } /** * $prevstateoverrides = true will set the visibility of the course module @@ -2218,7 +2247,7 @@ foreach ($grade_items as $grade_item) { $grade_item->delete('moddelete'); } - + } return delete_records('course_modules', 'id', $cm->id); } @@ -2432,7 +2461,7 @@ ' alt="'.$str->movedown.'" />'."\n"; } } else { - $move = ''; + $move = ''; } $leftright = ''; @@ -2445,7 +2474,7 @@ $rightarrow = 'right.gif'; $leftarrow = 'left.gif'; } - + if ($indent > 0) { $leftright .= ''; echo ''.get_string('grouping', 'group').':'; echo ''; - + $groupings; $groupingid = isset($cm->groupingid) ? $cm->groupingid : 0; - + choose_from_menu($groupings, 'groupingid', $groupingid, get_string('none'), '', 0, false); echo ''; - + $checked = empty($cm->groupmembersonly) ? '':'checked="checked"'; echo ''; echo ''.get_string('groupmembersonly', 'group').':'; @@ -2743,10 +2772,10 @@ context_moved($context, $newparent); - // The most effective thing would be to find the common parent, + // The most effective thing would be to find the common parent, // until then, do it sitewide... fix_course_sortorder(); - + return true; } @@ -2792,7 +2821,7 @@ } -/* +/* * Create a course and either return a $course object or false * * @param object $data - all the data needed for an entry in the 'course' table @@ -2842,13 +2871,13 @@ add_to_log(SITEID, 'course', 'new', 'view.php?id='.$course->id, $data->fullname.' (ID '.$course->id.')'); return $course; - } + } return false; // error } -/* +/* * Update a course and return true or false * * @param object $data - all the data needed for an entry in the 'course' table @@ -2898,37 +2927,37 @@ // put custom role names into db $context = get_context_instance(CONTEXT_COURSE, $course->id); - + foreach ($data as $dname => $dvalue) { - + // is this the right param? $dvalue = clean_param($dvalue, PARAM_NOTAGS); if (!strstr($dname, 'role_')) { continue; - } - + } + $dt = explode('_', $dname); $roleid = $dt[1]; // make up our mind whether we want to delete, update or insert - + if (empty($dvalue)) { - + delete_records('role_names', 'contextid', $context->id, 'roleid', $roleid); - + } else if ($t = get_record('role_names', 'contextid', $context->id, 'roleid', $roleid)) { - + $t->text = $dvalue; - update_record('role_names', $t); - + update_record('role_names', $t); + } else { - + $t->contextid = $context->id; $t->roleid = $roleid; $t->text = $dvalue; - insert_record('role_names', $t); + insert_record('role_names', $t); } - + } return true; Index: lib/db/upgrade.php =================================================================== RCS file: /cvsroot/moodle/moodle/lib/db/upgrade.php,v retrieving revision 1.168 diff -u -r1.168 upgrade.php --- lib/db/upgrade.php 8 Dec 2007 18:44:12 -0000 1.168 +++ lib/db/upgrade.php 20 Dec 2007 14:05:28 -0000 @@ -2054,6 +2054,9 @@ /// Launch create table for context_temp $result = $result && create_table($table); + /// make sure category depths, parents and paths are ok, categories from 1.5 may not be properly initialized (MDL-12585) + upgrade_fix_category_depths(); + /// Recalculate depths, paths and so on if (!empty($CFG->rolesactive)) { cleanup_contexts(); @@ -2309,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 @@ -2354,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')); @@ -2516,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); @@ -2539,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; } @@ -2575,30 +2578,30 @@ $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); } else { // 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")) { @@ -2626,13 +2629,59 @@ /// Main savepoint reached upgrade_main_savepoint($result, 2007101502); - } + } if ($result && $oldversion < 2007101503) { // Update courses that used weekscss to weeks $result = $result && set_field('course', 'format', 'weeks', 'format', 'weekscss'); } + if ($result && $oldversion < 2007101505) { + + /// Changing precision of field dst_time on table timezone to (6) + $table = new XMLDBTable('timezone'); + $field = new XMLDBField('dst_time'); + $field->setAttributes(XMLDB_TYPE_CHAR, '6', null, XMLDB_NOTNULL, null, null, null, '00:00', 'dst_skipweeks'); + + /// Launch change of precision for field dst_time + $result = $result && change_field_precision($table, $field); + + /// Changing precision of field std_time on table timezone to (6) + $table = new XMLDBTable('timezone'); + $field = new XMLDBField('std_time'); + $field->setAttributes(XMLDB_TYPE_CHAR, '6', null, XMLDB_NOTNULL, null, null, null, '00:00', 'std_skipweeks'); + + /// Launch change of precision for field std_time + $result = $result && change_field_precision($table, $field); + + /// Main savepoint reached + upgrade_main_savepoint($result, 2007101505); + } + + if ($result && $oldversion < 2007101506) { + + // 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); + //$index->setAttributes(XMLDB_INDEX_UNIQUE, array('itemtype', 'itemid', 'tagid', 'tiuserid')); + $result = $result && add_index($table, $index); + + /// Main savepoint reached + upgrade_main_savepoint($result, 2007101506); + } + return $result; } Index: lib/db/install.xml =================================================================== RCS file: /cvsroot/moodle/moodle/lib/db/install.xml,v retrieving revision 1.136 diff -u -r1.136 install.xml --- lib/db/install.xml 8 Nov 2007 02:01:34 -0000 1.136 +++ lib/db/install.xml 20 Dec 2007 14:05:27 -0000 @@ -1,5 +1,5 @@ - @@ -419,12 +419,12 @@ - + - + @@ -1516,8 +1516,9 @@ - - + + + @@ -1525,7 +1526,7 @@ - + Index: lang/en_utf8/tag.php =================================================================== RCS file: /cvsroot/moodle/moodle/lang/en_utf8/tag.php,v retrieving revision 1.12 diff -u -r1.12 tag.php --- lang/en_utf8/tag.php 16 Sep 2007 20:19:20 -0000 1.12 +++ lang/en_utf8/tag.php 20 Dec 2007 14:05:24 -0000 @@ -37,6 +37,7 @@ $string['tags'] = 'Tags'; $string['tagsaredisabled'] = 'Tags are disabled'; $string['thingstaggedwith'] = '$a->count things tagged with \"$a->name\"'; +$string['thingtaggedwith'] = '$a->count thing tagged with \"$a->name\"'; $string['thistaghasnodesc'] = 'This tag currently has no description.'; $string['timemodified'] = 'Modified'; $string['typechanged'] = 'Tag type changed'; Index: version.php =================================================================== RCS file: /cvsroot/moodle/moodle/version.php,v retrieving revision 1.571 diff -u -r1.571 version.php --- version.php 21 Nov 2007 07:53:42 -0000 1.571 +++ version.php 20 Dec 2007 14:05:23 -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 = 2007101504; // YYYYMMDD = date + $version = 2007101506; // 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.977 diff -u -r1.977 moodlelib.php --- lib/moodlelib.php 17 Dec 2007 23:44:25 -0000 1.977 +++ lib/moodlelib.php 20 Dec 2007 14:05:26 -0000 @@ -234,6 +234,7 @@ * PAGE_COURSE_VIEW is a definition of a page type. For more information on the page class see moodle/lib/pagelib.php. */ define('PAGE_COURSE_VIEW', 'course-view'); +define('PAGE_MOD_VIEW', 'mod-view'); /// Debug levels /// /** no warnings at all */ @@ -611,11 +612,17 @@ global $CFG; if (empty($plugin)) { - $CFG->$name = $value; // So it's defined for this invocation at least + if (!array_key_exists($name, $CFG->config_php_settings)) { + // So it's defined for this invocation at least + if (is_null($value)) { + unset($CFG->$name); + } else { + $CFG->$name = (string)$value; // settings from db are always strings + } + } if (get_field('config', 'name', 'name', $name)) { if ($value===null) { - unset($CFG->$name); return delete_records('config', 'name', $name); } else { return set_field('config', 'value', addslashes($value), 'name', $name); @@ -697,14 +704,9 @@ foreach ($configs as $config) { if (!isset($localcfg[$config->name])) { $localcfg[$config->name] = $config->value; - } else { - if ($localcfg[$config->name] != $config->value ) { - // complain if the DB has a different - // value than config.php does - error_log("\$CFG->{$config->name} in config.php ({$localcfg[$config->name]}) overrides database setting ({$config->value})"); } + // do not complain anymore if config.php overrides settings from db } - } $localcfg = (object)$localcfg; return $localcfg; @@ -1874,12 +1876,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')); } @@ -1891,7 +1893,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 @@ -1900,14 +1902,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)) { @@ -1922,7 +1924,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"); @@ -1970,7 +1972,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 @@ -3030,7 +3032,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. * @@ -3042,7 +3044,7 @@ */ function complete_user_login($user) { global $CFG, $USER; - + $USER = $user; // should not be needed, but cover for legacy code update_user_login_times(); @@ -3541,6 +3543,11 @@ /// 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); + notify("$strdeleted course tags"); + return $result; } @@ -4343,7 +4350,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; @@ -4357,20 +4364,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) { @@ -4378,7 +4385,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) { @@ -4388,7 +4395,7 @@ } } } - } + } } } else { notify("$rootdir does not exist!"); @@ -6357,7 +6364,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) { @@ -6369,7 +6376,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); @@ -6425,7 +6432,7 @@ $truncate .= $line_matchings[2]; $total_length += $content_length; } - + // if the maximum length is reached, get off the loop if($total_length >= $ideal) { break; @@ -6446,7 +6453,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.

Index: blocks/tags/coursetags_more.php =================================================================== RCS file: blocks/tags/coursetags_more.php diff -N blocks/tags/coursetags_more.php --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ blocks/tags/coursetags_more.php 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,192 @@ +dirroot.'/blocks/tags/coursetagslib.php'); +require_once($CFG->dirroot.'/tag/lib.php'); + +$sort = optional_param('sort', 'alpha', PARAM_TEXT); //alpha, date or popularity +$show = optional_param('show', 'all', PARAM_TEXT); //all, my, official, community or course +$courseid = optional_param('courseid', 0, PARAM_INT); + +// Some things require logging in +if ($CFG->forcelogin or $show == 'my') { + require_login(); +} + +// Permissions +$sitecontext = get_context_instance(CONTEXT_SYSTEM, SITEID); +$isguest = has_capability('moodle/legacy:guest', $sitecontext, $USER->id, false); +$loggedin = isloggedin() && !$isguest; + +// Course check +if ($courseid) { + if (!($course = get_record('course', 'id', $courseid))) { + $courseid = 0; + } + if ($courseid == SITEID) $courseid = 0; +} + +// Language strings +$tagslang = 'block_tags'; +$title = get_string('moretitle', $tagslang); +$link1 = get_string('moreshow', $tagslang); +$link2 = get_string('moreorder', $tagslang); +$showalltags = get_string('moreshowalltags', $tagslang); +$showofficialtags = get_string('moreshowofficialtags', $tagslang); +$showmytags = get_string('moreshowmytags', $tagslang); +$showcommtags = get_string('moreshowcommtags', $tagslang); +$tagsfor = get_string('moretagsfor', $tagslang); +$orderalpha = get_string('moreorderalpha', $tagslang); +$orderdate = get_string('moreorderdate', $tagslang); +$orderpop = get_string('moreorderpop', $tagslang); +$mytags = get_string('moremytags', $tagslang); +$officialtags = get_string('moreofficialtags', $tagslang); +$communitytags = get_string('morecommtags', $tagslang); +$alltags = get_string('morealltags', $tagslang); +$welcome = get_string('morewelcome', $tagslang); + +// The title and breadcrumb +if ($courseid) { + $navigation[] = array('name' => $course->shortname, 'link' => $CFG->wwwroot.'/course/view.php?id='.$courseid, 'type' => 'misc'); + $navigation[] = array('name' => $title, 'link' => null, 'type' => 'misc'); +} else { + $navigation[] = array('name' => $title, 'link' => null, 'type' => 'misc'); +} +$nav = build_navigation($navigation); +print_header_simple($title, '', $nav, '', '', false); +print_heading($title, 'centre'); + +// Prepare data for tags +$courselink = ''; +if ($courseid) $courselink = '&courseid='.$courseid; +$myurl = $CFG->wwwroot.'/blocks/tags/coursetags_more.php'; +$myurl2 = $CFG->wwwroot.'/blocks/tags/coursetags_more.php?show='.$show; + +// Course tags +if ($show == 'course' and $courseid) { + + if ($sort == 'popularity') { + $tags = print_tag_cloud(coursetag_get_tags($courseid, 0, '', 0, 'popularity'), false, 200, 90, true); + } else if ($sort == 'date') { + $tags = print_tag_cloud(coursetag_get_tags($courseid, 0, '', 0, 'timemodified'), false, 200, 90, true); + } else { + $tags = print_tag_cloud(coursetag_get_tags($courseid, 0, '', 0, 'name'), false, 200, 90, true); + } + +// My tags +} else if ($show == 'my' and $loggedin) { + + if ($sort == 'popularity') { + $tags = print_tag_cloud(coursetag_get_tags(0, $USER->id, 'personal', 0, 'popularity'), false, 200, 90, true); + } else if ($sort == 'date') { + $tags = print_tag_cloud(coursetag_get_tags(0, $USER->id, 'personal', 0, 'timemodified'), false, 200, 90, true); + } else { + $tags = print_tag_cloud(coursetag_get_tags(0, $USER->id, 'personal', 0, 'name'), false, 200, 90, true); + } + +// Official course tags +} else if ($show == 'official') { + + if ($sort == 'popularity') { + $tags = print_tag_cloud(coursetag_get_tags(0, 0, 'official', 0, 'popularity'), false, 200, 90, true); + } else if ($sort == 'date') { + $tags = print_tag_cloud(coursetag_get_tags(0, 0, 'official', 0, 'timemodified'), false, 200, 90, true); + } else { + $tags = print_tag_cloud(coursetag_get_tags(0, 0, 'official', 0, 'name'), false, 200, 90, true); + } + +// Community (official and personal together) also called user tags +} else if ($show == 'community') { + + if ($sort == 'popularity') { + $tags = print_tag_cloud(coursetag_get_tags(0, 0, 'personal', 0, 'popularity'), false, 200, 90, true); + } else if ($sort == 'date') { + $tags = print_tag_cloud(coursetag_get_tags(0, 0, 'personal', 0, 'timemodified'), false, 200, 90, true); + } else { + $tags = print_tag_cloud(coursetag_get_tags(0, 0, 'personal', 0, 'name'), false, 200, 90, true); + } + +// All tags for courses and blogs and any thing else tagged - the fallback default ($show == all) +} else { + + $subtitle = $alltags; + if ($sort == 'popularity') { + $tags = print_tag_cloud(coursetag_get_all_tags('popularity'), false, 200, 90, true); + } else if ($sort == 'date') { + $tags = print_tag_cloud(coursetag_get_all_tags('timemodified'), false, 200, 90, true); + } else { + $tags = print_tag_cloud(coursetag_get_all_tags('name'), false, 200, 90, true); + } + +} + +// Prepare the links for the show and order lines +if ($show == 'all') { + $link1 .= ''.$showalltags.''; +} else { + $link1 .= ''.$showalltags.''; +} +if ($show == 'official') { + $link1 .= ' | '.$showofficialtags.''; +} else { + $link1 .= ' | '.$showofficialtags.''; +} +if ($show == 'community') { + $link1 .= ' | '.$showcommtags.''; +} else { + $link1 .= ' | '.$showcommtags.''; +} +if ($loggedin) { + if ($show == 'my') { + $link1 .= ' | '.$showmytags.''; + } else { + $link1 .= ' | '.$showmytags.''; + } +} +if ($courseid) { + if ($show == 'course') { + $link1 .= ' | '.$tagsfor.' \''.$course->fullname.'\''; + } else { + $link1 .= ' | '.$tagsfor.' \''.$course->fullname.'\''; + } +} +if ($sort == 'alpha') { + $link2 .= ''.$orderalpha.' | '; +} else { + $link2 .= ''.$orderalpha.' | '; +} +if ($sort == 'popularity') { + $link2 .= ''.$orderpop.' | '; +} else { + $link2 .= ''.$orderpop.' | '; +} +if ($sort == 'date') { + $link2 .= ''.$orderdate.''; +} else { + $link2 .= ''.$orderdate.''; +} + +// Prepare output +$fclass = ''; +// make the tags larger when there are not so many +if (strlen($tags) < 10000) $fclass = 'coursetag_more_large'; +$outstr = ' +
+
'.$welcome. + helpbutton('usingtags', 'using tags', $tagslang, TRUE, FALSE, '', TRUE).' +
+ + +
+
'. + $tags.' +
'; +echo $outstr; + +print_footer(); +?> Index: blocks/tags/coursetags_add.php =================================================================== RCS file: blocks/tags/coursetags_add.php diff -N blocks/tags/coursetags_add.php --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ blocks/tags/coursetags_add.php 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,37 @@ +dirroot.'/blocks/tags/coursetagslib.php'); + + if ($entryid > 0 and $userid > 0) { + $myurl = 'tag/search.php?query='.urlencode($keyword); + $keywords = (array)$keyword; + try { + coursetag_store_keywords($keywords, $entryid, $userid, 'personal', $myurl); + } + catch (Exception $e) { + error($e->getmessage()); + } + } +} + +// send back to originating page, where the new tag will be visible in the block +if ($entryid > 0) { + $myurl = $CFG->wwwroot.'/course/view.php?id='.$entryid; +} else { + $myurl = $CFG->wwwroot.'/'; +} +redirect($myurl); +?> Index: blocks/tags/arrow_left.gif =================================================================== RCS file: blocks/tags/arrow_left.gif diff -N blocks/tags/arrow_left.gif --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ blocks/tags/arrow_left.gif 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,5 @@ +GIF89a + +¢fffÿ̰°°ÿÿÿÝÝݵµµ!ù, + +º¼M?Û$/‡KºB'Œ#„ÙãU¤Fp?; Index: lang/en_utf8/help/block_tags/addtags.html =================================================================== RCS file: lang/en_utf8/help/block_tags/addtags.html diff -N lang/en_utf8/help/block_tags/addtags.html --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lang/en_utf8/help/block_tags/addtags.html 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,27 @@ +

Adding a tag for a course

+ +

Logged on users may 'tag' courses.

+ +

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/styles.php =================================================================== RCS file: blocks/tags/styles.php diff -N blocks/tags/styles.php --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ blocks/tags/styles.php 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,108 @@ +/* + * CSS for course tags + * @author j.beedell@open.ac.uk July07 + * + * Styles for block_tags.php + */ + +.coursetag_form_positioner { + position: relative; + margin: 5px 0 0 0; + height: 25px; +} + +.coursetag_form_input1 { + position: absolute; + top: 0; + left: 0; + z-index: 1; +} + +.coursetag_form_input2 { + position: absolute; + top: 0; + left: 0; + z-index: 2; + width: 10em; +} + +.coursetag_form_input3 { + position: absolute; + top: 3px; + left: 13em; + display: none; +} + +.coursetag_form_input1a { + background-color: transparent; + border: 1px solid #999; + width: 12em; + padding: 2px +} + +.coursetag_form_input2a { + background: transparent; + color: #669954; + border: 1px solid #999; + width: 12em; + padding: 2px +} + +.coursetag_morelink { + float: right; + font-size: 0.8em; + margin: -10px 5px 5px 0; +} + +/* Styles for edit_tags.php */ + +.coursetag_edit_centered { + position: relative; + width: 600px; + margin: 20px auto; +} + +.coursetag_edit_row { + margin: 5px 0 5px 0; + height: 30px; +} + +.coursetag_edit_left { + position: relative; + float: left; + padding: 3px 5px; +} + +.coursetag_edit_right { + position: relative; + float: left; + padding: 3px 0px; +} + +.coursetag_edit_input3 { + position: relative; + left: 10.5em; + display: none; +} + +/* Styles for more_tags.php */ + +.coursetag_more_title { + margin: 30px 30px -25px 30px; +} + +.coursetag_more_tags { + margin: 30px; +} + +.coursetag_more_large { + font-size: 120% +} + +.coursetag_more_small { + font-size: 80% +} + +.coursetag_more_link { + font-size: 80%; +} Index: blocks/tags/coursetags.js =================================================================== RCS file: blocks/tags/coursetags.js diff -N blocks/tags/coursetags.js --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ blocks/tags/coursetags.js 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,79 @@ +/** + * coursetags.js + * @author j.beedell@open.ac.uk July07 + * + * getKeywords modified from an original script (Auto Complete Textfield) + * from The JavaScript Source http://javascript.internet.com + * originally created by: Timothy Groves http://www.brandspankingnew.net/ + */ + + +function ctags_show_div(mydiv) { + for(x in coursetagdivs) { + if(mydiv == coursetagdivs[x]) { + document.getElementById(coursetagdivs[x]).style.display="block"; + } else { + document.getElementById(coursetagdivs[x]).style.display="none"; + } + } + return false; +} + +function ctags_checkinput(val) { + var len = val.length; + if (len < 2 || len > 50) { + alert("Tags must have more that one and less than 50 characters. Please adjust your tag."); + return false; + } else if (val.indexOf("'") > 0) { + alert("Regretably tags cannot contain apostrophies at the moment. Please adjust your tag."); + return false; + } else if (val.indexOf("_") > 0) { + alert("Tags cannot contain underscores. Please adjust your tag."); + return false; + } else if (val.indexOf("-") > 0) { + alert("Tags cannot contain hyphens. Please adjust your tag."); + return false; + } else if (isFinite(val)) { + alert("Tags cannot be an integer or float. Please adjust your tag."); + return false; + } else { + return true; + } +} + +var sug = ""; +var sug_disp = ""; + +function ctags_getKeywords() { + var input = document.forms['coursetag'].coursetag_new_tag.value; + var len = input.length; + sug_disp = ""; sug = ""; + + if (input.length) { + // get matching folks_tag from array + for (ele in coursetag_tags) + { + if (coursetag_tags[ele].substr(0,len).toLowerCase() == input.toLowerCase()) + { + sug_disp = input + coursetag_tags[ele].substr(len); + sug = coursetag_tags[ele]; + break; + } + } + } + document.forms['coursetag'].coursetag_sug_keyword.value = sug_disp; + if (!sug.length || input == sug_disp) + document.getElementById('coursetag_sug_btn').style.display = "none"; + else + document.getElementById('coursetag_sug_btn').style.display = "block"; +} + +function ctags_setKeywords() { + document.forms['coursetag'].coursetag_new_tag.value = sug; + ctags_hideSug(); +} + +function ctags_hideSug() { + document.forms['coursetag'].coursetag_sug_keyword.value = ""; + document.getElementById('coursetag_sug_btn').style.display = "none"; +} 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,443 @@ +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'); + // 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) { + $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 because rsslib needs updating to accept dc/cc input before this can work. + */ +/* +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 + * + * 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: 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.

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 = '
'; + if ($coursetabs) { + $outstr .= get_string('editmytagsfor', $tagslang)." \"{$COURSE->fullname}\" ". + get_string('editare', $tagslang)." $coursetabs."; + } else { + $outstr .= get_string('editnopersonaltags', $tagslang)." '{$COURSE->fullname}' ". + get_string('edityet', $tagslang); + } + $outstr .= '
'; + echo $outstr; + + // Getting deletions and additions to personal tags for a unit + $outstr = " + "; + $outstr .= coursetag_get_jscript(); + $outstr .= " + + + +
+
+
"; + $outstr .= helpbutton('addtags', 'adding tags', $tagslang, TRUE, FALSE, '', TRUE); + $outstr .= get_string('edittagthisunit', $tagslang).' '; + $outstr .= "
+
+
+ +
+
+ +
+
+ + + +
+
+
"; + if ($coursetabs) { + $outstr .= " +
+
"; + $outstr .= helpbutton('deletetags', 'deleting tags', $tagslang, TRUE, FALSE, '', TRUE); + $outstr .= get_string('editdeletemytag', $tagslang).' '; + $outstr .= "
+
+ +
+
"; + } + $outstr .= " +
+
+ +
+
+ "; + echo $outstr; + } + +} + +print_footer(); +?>