diff --git a/tag/locallib.php b/tag/locallib.php
new file mode 100644
index 00000000000..98d2fdc466b
--- /dev/null
+++ b/tag/locallib.php
@@ -0,0 +1,377 @@
+prefix .'tag_instance ti INNER JOIN '. $CFG->prefix .'tag tg ON tg.id = ti.tagid '.
+ 'GROUP BY tg.id, tg.rawname, tg.name, tg.flag '.
+ 'ORDER BY count DESC';
+
+ $tagcloud = get_records_sql($query, 0, $nr_of_tags);
+
+ if ($shuffle) {
+ shuffle($tagcloud);
+ } else {
+ ksort($tagcloud);
+ }
+
+ $count = array();
+ foreach ($tagcloud as $key => $tag){
+ if(!empty($tag->count)) {
+ $count[$key] = log10($tag->count);
+ }
+ else{
+ $count[$key] = 0;
+ }
+ }
+
+ $max = max($count);
+ $min = min($count);
+
+ $spread = $max - $min;
+ if (0 == $spread) { // we don't want to divide by zero
+ $spread = 1;
+ }
+
+ $step = ($max_size - $min_size)/($spread);
+
+ $systemcontext = get_context_instance(CONTEXT_SYSTEM);
+ $can_manage_tags = has_capability('moodle/tag:manage', $systemcontext);
+
+ //prints the tag cloud
+ $output = '
';
+ foreach ($tagcloud as $key => $tag) {
+
+ $size = $min_size + ((log10($tag->count) - $min) * $step);
+ $size = ceil($size);
+
+ $style = 'style="font-size: '. $size .'%"';
+ $title = 'title="'. s(get_string('thingstaggedwith', 'tag', $tag)) .'"';
+ $href = 'href="'. $CFG->wwwroot .'/tag/index.php?tag='. rawurlencode($tag->name) .'"';
+
+ //highlight tags that have been flagged as inappropriate for those who can manage them
+ $tagname = tag_display_name($tag);
+ if ($tag->flag > 0 && $can_manage_tags) {
+ $tagname = ''. tag_display_name($tag) .'';
+ }
+
+ $tag_link = '- '. $tagname .'
';
+
+ $output .= $tag_link;
+ }
+ $output .= '
';
+
+ if ($return) {
+ return $output;
+ } else {
+ echo $output;
+ }
+}
+
+/**
+ * Prints a box with the description of a tag and its related tags
+ *
+ * @param unknown_type $tag_object
+ * @param $return if true return html string
+ */
+function tag_print_description_box($tag_object, $return=false) {
+
+ global $USER, $CFG;
+
+ $tagname = tag_display_name($tag_object);
+ $related_tags = tag_get_related_tags($tag_object->id);
+
+ $content = !empty($tag_object->description) || $related_tags;
+ $output = '';
+
+ if ($content) {
+ $output .= print_box_start('generalbox', 'tag-description', true);
+ }
+
+ if (!empty($tag_object->description)) {
+ $options = new object();
+ $options->para = false;
+ $output .= format_text($tag_object->description, $tag_object->descriptionformat, $options);
+ }
+
+ if ($related_tags) {
+ $output .= '
'. get_string('relatedtags', 'tag') .': '. tag_get_related_tags_csv($related_tags);
+ }
+
+ if ($content) {
+ $output .= print_box_end(true);
+ }
+
+ if ($return) {
+ return $output;
+ } else {
+ echo $output;
+ }
+}
+
+/**
+ * Prints a box that contains the management links of a tag
+ *
+ * @param $tagid
+ * @param $return if true return html string
+ */
+function tag_print_management_box($tag_object, $return=false) {
+
+ global $USER, $CFG;
+
+ $tagname = tag_display_name($tag_object);
+ $output = '';
+
+ if (!isguestuser()) {
+ $output .= print_box_start('box','tag-management-box', true);
+ $systemcontext = get_context_instance(CONTEXT_SYSTEM);
+ $links = array();
+
+ // if the user is not tagged with the $tag_object tag, a link "add blahblah to my interests" will appear
+ if( !tag_record_tagged_with(array('type'=>'user', 'id'=>$USER->id), $tag_object->name )) {
+ $links[] = ''. get_string('addtagtomyinterests', 'tag', $tagname) .'';
+ }
+
+ // only people with moodle/tag:edit capability may edit the tag description
+ if ( has_capability('moodle/tag:edit', $systemcontext) && tag_record_tagged_with(array('type'=>'user', 'id'=>$USER->id), $tag_object->name ) ) {
+ $links[] = ''. get_string('edittag', 'tag') .'';
+ }
+
+ // flag as inappropriate link
+ $links[] = ''. get_string('flagasinappropriate', 'tag', rawurlencode($tagname)) .'';
+
+ // Manage all tags links
+ if ( has_capability('moodle/tag:manage', $systemcontext) ) {
+ $links[] = ''. get_string('managetags', 'tag') .'' ;
+ }
+
+ $output .= implode(' | ', $links);
+ $output .= print_box_end(true);
+ }
+
+ if ($return) {
+ return $output;
+ } else {
+ echo $output;
+ }
+}
+
+/**
+ * Prints the tag search box
+ *
+ * @param bool $return if true return html string
+ */
+function tag_print_search_box($return=false) {
+ global $CFG;
+
+ $output = print_box_start('','tag-search-box', true);
+ $output .= '';
+ $output .= print_box_end(true);
+
+ if ($return) {
+ return $output;
+ }
+ else {
+ echo $output;
+ }
+}
+
+/**
+ * Prints the tag search results
+ *
+ * @param string $query text that tag names will be matched against
+ * @param int $page current page
+ * @param int $perpage nr of users displayed per page
+ * @param $return if true return html string
+ */
+function tag_print_search_results($query, $page, $perpage, $return=false) {
+
+ global $CFG, $USER;
+
+ $count = sizeof(tag_search($query, false));
+ $tags = array();
+
+ if ( $found_tags = tag_search($query, true, $page * $perpage, $perpage) ) {
+ $tags = array_values($found_tags);
+ }
+
+ $baseurl = $CFG->wwwroot.'/tag/search.php?query='. rawurlencode($query);
+ $output = '';
+
+ // link "Add $query to my interests"
+ $addtaglink = '';
+ if( !is_item_tagged_with('user', $USER->id, $query) ) {
+ $addtaglink = '';
+ $addtaglink .= get_string('addtagtomyinterests', 'tag', rawurlencode($query)) .'';
+ }
+
+ if ( !empty($tags) ) { // there are results to display!!
+ $output .= print_heading(get_string('searchresultsfor', 'tag', rawurlencode($query)) ." : {$count}", '', 3, 'main', true);
+
+ //print a link "Add $query to my interests"
+ if (!empty($addtaglink)) {
+ $output .= print_box($addtaglink, 'box', 'tag-management-box', true);
+ }
+
+ $nr_of_lis_per_ul = 6;
+ $nr_of_uls = ceil( sizeof($tags) / $nr_of_lis_per_ul );
+
+ $output .= '';
+ for($i = 0; $i < $nr_of_uls; $i++) {
+ $output .= '- ';
+ foreach (array_slice($tags, $i * $nr_of_lis_per_ul, $nr_of_lis_per_ul) as $tag) {
+ $tag_link = ' '. tag_display_name($tag) .'';
+ $output .= '•'. $tag_link .'
';
+ }
+ $output .= ' ';
+ }
+ $output .= '
';
+ $output .= '
'; // <-- small layout hack in order to look good in Firefox
+
+ $output .= print_paging_bar($count, $page, $perpage, $baseurl .'&', 'page', false, true);
+ }
+ else { //no results were found!!
+ $output .= print_heading(get_string('noresultsfor', 'tag', rawurlencode($query)), '', 3, 'main' , true);
+
+ //print a link "Add $query to my interests"
+ if (!empty($addtaglink)) {
+ $output .= print_box($addtaglink, 'box', 'tag-management-box', true);
+ }
+ }
+
+ if ($return) {
+ return $output;
+ }
+ else {
+ echo $output;
+ }
+}
+
+/**
+ * Prints a table of the users tagged with the tag passed as argument
+ *
+ * @param $tag_object
+ * @param int $users_per_row number of users per row to display
+ * @param int $limitfrom prints users starting at this point (optional, required if $limitnum is set).
+ * @param int $limitnum prints this many users (optional, required if $limitfrom is set).
+ * @param $return if true return html string
+ */
+function tag_print_tagged_users_table($tag_object, $limitfrom='' , $limitnum='', $return=false) {
+
+ //List of users with this tag
+ $userlist = tag_find_records($tag_object->name, 'user');
+
+ $output = tag_print_user_list($userlist, true);
+
+ if ($return) {
+ return $output;
+ }
+ else {
+ echo $output;
+ }
+}
+
+/**
+ * Prints an individual user box
+ *
+ * @param $user user object (contains the following fields: id, firstname, lastname and picture)
+ * @param $return if true return html string
+ */
+function tag_print_user_box($user, $return=false) {
+ global $CFG;
+
+ $textlib = textlib_get_instance();
+ $usercontext = get_context_instance(CONTEXT_USER, $user->id);
+ $profilelink = '';
+
+ if ( has_capability('moodle/user:viewdetails', $usercontext) ) {
+ $profilelink = $CFG->wwwroot .'/user/view.php?id='. $user->id;
+ }
+
+ $output = print_box_start('user-box', 'user'. $user->id, true);
+ $fullname = fullname($user);
+ $alt = '';
+
+ if (!empty($profilelink)) {
+ $output .= '';
+ $alt = $fullname;
+ }
+
+ //print user image - if image is only content of link it needs ALT text!
+ if ($user->picture) {
+ $output .= '
';
+ } else {
+ $output .= '
';
+ }
+
+ $output .= '
';
+
+ if (!empty($profilelink)) {
+ $output .= '';
+ }
+
+ //truncate name if it's too big
+ if ($textlib->strlen($fullname) > 26) {
+ $fullname = $textlib->substr($fullname, 0, 26) .'...';
+ }
+
+ $output .= ''. $fullname .'';
+ $output .= print_box_end(true);
+
+ if ($return) {
+ return $output;
+ }
+ else {
+ echo $output;
+ }
+}
+/**
+ * Prints a list of users
+ *
+ * @param array $userlist an array of user objects
+ * @param $return if true return html string
+ */
+function tag_print_user_list($userlist, $return=false) {
+
+ $output = '';
+
+ foreach ($userlist as $user){
+ $output .= '- '. tag_print_user_box($user, true) ."
\n";
+ }
+ $output .= "
\n";
+
+ if ($return) {
+ return $output;
+ }
+ else {
+ echo $output;
+ }
+}
+
+
+?>