Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/tag/lib.php
Go to the documentation of this file.
00001 <?php
00002 
00003 // This file is part of Moodle - http://moodle.org/
00004 //
00005 // Moodle is free software: you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation, either version 3 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // Moodle is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
00017 
00053 define('TAG_RETURN_ARRAY', 0);
00054 define('TAG_RETURN_OBJECT', 1);
00055 define('TAG_RETURN_TEXT', 2);
00056 define('TAG_RETURN_HTML', 3);
00057 
00058 define('TAG_CASE_LOWER', 0);
00059 define('TAG_CASE_ORIGINAL', 1);
00060 
00061 define('TAG_RELATED_ALL', 0);
00062 define('TAG_RELATED_MANUAL', 1);
00063 define('TAG_RELATED_CORRELATED', 2);
00064 
00067 
00069 
00083 function tag_set($record_type, $record_id, $tags) {
00084 
00085     static $in_recursion_semaphore = false; // this is to prevent loops when tagging a tag
00086     if ( $record_type == 'tag' && !$in_recursion_semaphore) {
00087         $current_tagged_tag_name = tag_get_name($record_id);
00088     }
00089 
00090     $tags_ids = tag_get_id($tags, TAG_RETURN_ARRAY); // force an array, even if we only have one tag.
00091     $cleaned_tags = tag_normalize($tags);
00092     //echo 'tags-in-tag_set'; var_dump($tags); var_dump($tags_ids); var_dump($cleaned_tags);
00093 
00094     $current_ids = tag_get_tags_ids($record_type, $record_id);
00095     //var_dump($current_ids);
00096 
00097     // for data coherence reasons, it's better to remove deleted tags
00098     // before adding new data: ordering could be duplicated.
00099     foreach($current_ids as $current_id) {
00100         if (!in_array($current_id, $tags_ids)) {
00101             tag_delete_instance($record_type, $record_id, $current_id);
00102             if ( $record_type == 'tag' && !$in_recursion_semaphore) {
00103                 // if we are removing a tag-on-a-tag (manually related tag),
00104                 // we need to remove the opposite relationship as well.
00105                 tag_delete_instance('tag', $current_id, $record_id);
00106             }
00107         }
00108     }
00109 
00110     if (empty($tags)) {
00111         return true;
00112     }
00113 
00114     foreach($tags as $ordering => $tag) {
00115         $tag = trim($tag);
00116         if (!$tag) {
00117             continue;
00118         }
00119 
00120         $clean_tag = $cleaned_tags[$tag];
00121         $tag_current_id = $tags_ids[$clean_tag];
00122 
00123         if ( is_null($tag_current_id) ) {
00124             // create new tags
00125             //echo "call to add tag $tag\n";
00126             $new_tag = tag_add($tag);
00127             $tag_current_id = $new_tag[$clean_tag];
00128         }
00129 
00130         tag_assign($record_type, $record_id, $tag_current_id, $ordering);
00131 
00132         // if we are tagging a tag (adding a manually-assigned related tag), we
00133         // need to create the opposite relationship as well.
00134         if ( $record_type == 'tag' && !$in_recursion_semaphore) {
00135             $in_recursion_semaphore = true;
00136             tag_set_add('tag', $tag_current_id, $current_tagged_tag_name);
00137             $in_recursion_semaphore = false;
00138         }
00139     }
00140 }
00141 
00151 function tag_set_add($record_type, $record_id, $tag) {
00152 
00153     $new_tags = array();
00154     foreach( tag_get_tags($record_type, $record_id) as $current_tag ) {
00155         $new_tags[] = $current_tag->rawname;
00156     }
00157     $new_tags[] = $tag;
00158 
00159     return tag_set($record_type, $record_id, $new_tags);
00160 }
00161 
00171 function tag_set_delete($record_type, $record_id, $tag) {
00172 
00173     $new_tags = array();
00174     foreach( tag_get_tags($record_type, $record_id) as $current_tag ) {
00175         if ($current_tag->name != $tag) {  // Keep all tags but the one specified
00176             $new_tags[] = $current_tag->name;
00177         }
00178     }
00179 
00180     return tag_set($record_type, $record_id, $new_tags);
00181 }
00182 
00192 function tag_type_set($tagid, $type) {
00193     global $DB;
00194 
00195     if ($tag = $DB->get_record('tag', array('id'=>$tagid), 'id')) {
00196         $tag->tagtype = $type;
00197         $tag->timemodified = time();
00198         return $DB->update_record('tag', $tag);
00199     }
00200     return false;
00201 }
00202 
00203 
00212 function tag_description_set($tagid, $description, $descriptionformat) {
00213     global $DB;
00214 
00215     if ($tag = $DB->get_record('tag', array('id'=>$tagid),'id')) {
00216         $tag->description = $description;
00217         $tag->descriptionformat = $descriptionformat;
00218         $tag->timemodified = time();
00219         return $DB->update_record('tag', $tag);
00220     }
00221     return false;
00222 }
00223 
00224 
00225 
00226 
00227 
00228 
00230 
00240 function tag_get($field, $value, $returnfields='id, name, rawname') {
00241     global $DB;
00242 
00243     if ($field == 'name') {
00244         $value = moodle_strtolower($value);   // To cope with input that might just be wrong case
00245     }
00246     return $DB->get_record('tag', array($field=>$value), $returnfields);
00247 }
00248 
00249 
00262 function tag_get_tags($record_type, $record_id, $type=null, $userid=0) {
00263     global $CFG, $DB;
00264 
00265     $params = array();
00266 
00267     if ($type) {
00268         $sql_type = "AND tg.tagtype = :type";
00269         $params['type'] = $type;
00270     } else {
00271         $sql_type = '';
00272     }
00273 
00274    $u = null;
00275     if ($userid) {
00276         $u =  "AND ti.tiuserid = :userid ";
00277         $params['userid'] = $userid;
00278     }
00279 
00280     $sql = "SELECT tg.id, tg.tagtype, tg.name, tg.rawname, tg.flag, ti.ordering
00281               FROM {tag_instance} ti
00282               JOIN {tag} tg ON tg.id = ti.tagid
00283               WHERE ti.itemtype = :recordtype AND ti.itemid = :recordid $u $sql_type
00284            ORDER BY ti.ordering ASC";
00285     $params['recordtype'] = $record_type;
00286     $params['recordid']   = $record_id;
00287 
00288     // if the fields in this query are changed, you need to do the same changes in tag_get_correlated_tags
00289     return $DB->get_records_sql($sql, $params);
00290     // This version of the query, reversing the ON clause, "correctly" returns
00291     // a row with NULL values for instances that are still in the DB even though
00292     // the tag has been deleted.  This shouldn't happen, but if it did, using
00293     // this query could help "clean it up".  This causes bugs at this time.
00294     //$tags = $DB->get_records_sql("SELECT ti.tagid, tg.tagtype, tg.name, tg.rawname, tg.flag, ti.ordering ".
00295     //    "FROM {tag_instance} ti LEFT JOIN {tag} tg ON ti.tagid = tg.id ".
00296     //    "WHERE ti.itemtype = '{$record_type}' AND ti.itemid = '{$record_id}' {$type} ".
00297     //    "ORDER BY ti.ordering ASC");
00298 }
00299 
00309 function tag_get_tags_array($record_type, $record_id, $type=null) {
00310     $tags = array();
00311     foreach(tag_get_tags($record_type, $record_id, $type) as $tag) {
00312         $tags[$tag->id] = tag_display_name($tag);
00313     }
00314     return $tags;
00315 }
00316 
00329 function tag_get_tags_csv($record_type, $record_id, $html=TAG_RETURN_HTML, $type=null) {
00330     global $CFG;
00331 
00332     $tags_names = array();
00333     foreach(tag_get_tags($record_type, $record_id, $type) as $tag) {
00334         if ($html == TAG_RETURN_TEXT) {
00335             $tags_names[] = tag_display_name($tag, TAG_RETURN_TEXT);
00336         } else { // TAG_RETURN_HTML
00337             $tags_names[] = '<a href="'. $CFG->wwwroot .'/tag/index.php?tag='. rawurlencode($tag->name) .'">'. tag_display_name($tag) .'</a>';
00338         }
00339     }
00340     return implode(', ', $tags_names);
00341 }
00342 
00350 function tag_get_tags_ids($record_type, $record_id) {
00351 
00352     $tag_ids = array();
00353     foreach (tag_get_tags($record_type, $record_id) as $tag) {
00354         if ( array_key_exists($tag->ordering, $tag_ids) ) {
00355             // until we can add a unique constraint, in table tag_instance,
00356             // on (itemtype, itemid, ordering), this is needed to prevent a bug
00357             // TODO : modify database in 2.0
00358             $tag->ordering++;
00359         }
00360         $tag_ids[$tag->ordering] = $tag->id;
00361     }
00362     ksort($tag_ids);
00363     return $tag_ids;
00364 }
00365 
00378 function tag_get_id($tags, $return_value=null) {
00379     global $CFG, $DB;
00380 
00381     static $tag_id_cache = array();
00382 
00383     $return_an_int = false;
00384     if (!is_array($tags)) {
00385         if(is_null($return_value) || $return_value == TAG_RETURN_OBJECT) {
00386             $return_an_int = true;
00387         }
00388         $tags = array($tags);
00389     }
00390 
00391     $result = array();
00392 
00393     //TODO: test this and see if it helps performance without breaking anything
00394     //foreach($tags as $key => $tag) {
00395     //    $clean_tag = moodle_strtolower($tag);
00396     //    if ( array_key_exists($clean_tag), $tag_id_cache) ) {
00397     //        $result[$clean_tag] = $tag_id_cache[$clean_tag];
00398     //        $tags[$key] = ''; // prevent further processing for this one.
00399     //    }
00400     //}
00401 
00402     $tags = array_values(tag_normalize($tags));
00403     foreach($tags as $key => $tag) {
00404         $tags[$key] = moodle_strtolower($tag);
00405         $result[moodle_strtolower($tag)] = null; // key must exists : no value for a key means the tag wasn't found.
00406     }
00407 
00408     if (empty($tags)) {
00409         return array();
00410     }
00411 
00412     list($tag_string, $params) = $DB->get_in_or_equal($tags);
00413 
00414     $rs = $DB->get_recordset_sql("SELECT * FROM {tag} WHERE name $tag_string ORDER BY name", $params);
00415     foreach ($rs as $record) {
00416         if ($return_value == TAG_RETURN_OBJECT) {
00417             $result[$record->name] = $record;
00418         } else { // TAG_RETURN_ARRAY
00419             $result[$record->name] = $record->id;
00420         }
00421     }
00422     $rs->close();
00423 
00424     if ($return_an_int) {
00425         return array_pop($result);
00426     }
00427 
00428     return $result;
00429 }
00430 
00431 
00448 function tag_get_related_tags($tagid, $type=TAG_RELATED_ALL, $limitnum=10) {
00449 
00450     $related_tags = array();
00451 
00452     if ( $type == TAG_RELATED_ALL || $type == TAG_RELATED_MANUAL) {
00453         //gets the manually added related tags
00454         $related_tags = tag_get_tags('tag', $tagid);
00455     }
00456 
00457     if ( $type == TAG_RELATED_ALL || $type == TAG_RELATED_CORRELATED ) {
00458         //gets the correlated tags
00459         $automatic_related_tags = tag_get_correlated($tagid, $limitnum);
00460         if (is_array($automatic_related_tags)) {
00461             $related_tags = array_merge($related_tags, $automatic_related_tags);
00462         }
00463     }
00464 
00465     return array_slice(object_array_unique($related_tags), 0 , $limitnum);
00466 }
00467 
00475 function tag_get_related_tags_csv($related_tags, $html=TAG_RETURN_HTML) {
00476     global $CFG;
00477 
00478     $tags_names = array();
00479     foreach($related_tags as $tag) {
00480         if ( $html == TAG_RETURN_TEXT) {
00481             $tags_names[] = tag_display_name($tag, TAG_RETURN_TEXT);
00482         } else {
00483             // TAG_RETURN_HTML
00484             $tags_names[] = '<a href="'. $CFG->wwwroot .'/tag/index.php?tag='. rawurlencode($tag->name) .'">'. tag_display_name($tag) .'</a>';
00485         }
00486     }
00487 
00488     return implode(', ', $tags_names);
00489 }
00490 
00498 function tag_rename($tagid, $newrawname) {
00499     global $DB;
00500 
00501     if (! $newrawname_clean = array_shift(tag_normalize($newrawname, TAG_CASE_ORIGINAL)) ) {
00502         return false;
00503     }
00504 
00505     if (! $newname_clean = moodle_strtolower($newrawname_clean)) {
00506         return false;
00507     }
00508 
00509     // Prevent the rename if a tag with that name already exists
00510     if ($existing = tag_get('name', $newname_clean, 'id, name, rawname')) {
00511         if ($existing->id != $tagid) {  // Another tag already exists with this name
00512             return false;
00513         }
00514     }
00515 
00516     if ($tag = tag_get('id', $tagid, 'id, name, rawname')) {
00517         $tag->rawname      = $newrawname_clean;
00518         $tag->name         = $newname_clean;
00519         $tag->timemodified = time();
00520         return $DB->update_record('tag', $tag);
00521     }
00522     return false;
00523 }
00524 
00525 
00532 function tag_delete($tagids) {
00533     global $DB;
00534 
00535     if (!is_array($tagids)) {
00536         $tagids = array($tagids);
00537     }
00538 
00539     $success = true;
00540     $context = get_context_instance(CONTEXT_SYSTEM);
00541     foreach ($tagids as $tagid) {
00542         if (is_null($tagid)) { // can happen if tag doesn't exists
00543             continue;
00544         }
00545         // only delete the main entry if there were no problems deleting all the
00546         // instances - that (and the fact we won't often delete lots of tags)
00547         // is the reason for not using $DB->delete_records_select()
00548         if ($DB->delete_records('tag_instance', array('tagid'=>$tagid)) && $DB->delete_records('tag_correlation', array('tagid' => $tagid))) {
00549             $success &= (bool) $DB->delete_records('tag', array('id'=>$tagid));
00550             // Delete all files associated with this tag
00551             $fs = get_file_storage();
00552             $files = $fs->get_area_files($context->id, 'tag', 'description', $tagid);
00553             foreach ($files as $file) {
00554                 $file->delete();
00555             }
00556         }
00557     }
00558 
00559     return $success;
00560 }
00561 
00571 function tag_delete_instance($record_type, $record_id, $tagid) {
00572     global $CFG, $DB;
00573 
00574     if ($DB->delete_records('tag_instance', array('tagid'=>$tagid, 'itemtype'=>$record_type, 'itemid'=>$record_id))) {
00575         if (!$DB->record_exists_sql("SELECT * ".
00576                                       "FROM {tag} tg ".
00577                                      "WHERE tg.id = ? AND ( tg.tagtype = 'official' OR ".
00578                                         "EXISTS (SELECT 1
00579                                                    FROM {tag_instance} ti
00580                                                   WHERE ti.tagid = ?) )",
00581                                      array($tagid, $tagid))) {
00582             return tag_delete($tagid);
00583         }
00584     } else {
00585         return false;
00586     }
00587 
00588     return true;
00589 }
00590 
00591 
00599 function tag_display_name($tagobject, $html=TAG_RETURN_HTML) {
00600 
00601     global $CFG;
00602 
00603     if (!isset($tagobject->name)) {
00604         return '';
00605     }
00606 
00607     if (empty($CFG->keeptagnamecase)) {
00608         //this is the normalized tag name
00609         $textlib = textlib_get_instance();
00610         $tagname = $textlib->strtotitle($tagobject->name);
00611     } else {
00612         //original casing of the tag name
00613         $tagname = $tagobject->rawname;
00614     }
00615 
00616     // clean up a bit just in case the rules change again
00617     $tagname = clean_param($tagname, PARAM_TAG);
00618 
00619     if ($html == TAG_RETURN_TEXT) {
00620         return $tagname;
00621     } else { // TAG_RETURN_HTML
00622         return htmlspecialchars($tagname);
00623     }
00624 }
00625 
00636 function tag_find_records($tag, $type, $limitfrom='', $limitnum='') {
00637     global $CFG, $DB;
00638 
00639     if (!$tag || !$type) {
00640         return array();
00641     }
00642 
00643     $tagid = tag_get_id($tag);
00644 
00645     $query = "SELECT it.*
00646                 FROM {".$type."} it INNER JOIN {tag_instance} tt ON it.id = tt.itemid
00647                WHERE tt.itemtype = ? AND tt.tagid = ?";
00648     $params = array($type, $tagid);
00649 
00650     return $DB->get_records_sql($query, $params, $limitfrom, $limitnum);
00651 }
00652 
00653 
00654 
00655 
00658 
00670 function tag_add($tags, $type="default") {
00671     global $USER, $DB;
00672 
00673     if (!is_array($tags)) {
00674         $tags = array($tags);
00675     }
00676 
00677     $tag_object = new StdClass;
00678     $tag_object->tagtype      = $type;
00679     $tag_object->userid       = $USER->id;
00680     $tag_object->timemodified = time();
00681 
00682     $clean_tags = tag_normalize($tags, TAG_CASE_ORIGINAL);
00683 
00684     $tags_ids = array();
00685     foreach($clean_tags as $tag) {
00686         $tag = trim($tag);
00687         if (!$tag) {
00688             $tags_ids[$tag] = false;
00689         } else {
00690             // note that the difference between rawname and name is only
00691             // capitalization : the rawname is NOT the same at the rawtag.
00692             $tag_object->rawname = $tag;
00693             $tag_name_lc         = moodle_strtolower($tag);
00694             $tag_object->name    = $tag_name_lc;
00695             //var_dump($tag_object);
00696             $tags_ids[$tag_name_lc] = $DB->insert_record('tag', $tag_object);
00697         }
00698     }
00699 
00700     return $tags_ids;
00701 }
00702 
00714 function tag_assign($record_type, $record_id, $tagid, $ordering, $userid = 0) {
00715     global $DB;
00716 
00717     if ( $tag_instance_object = $DB->get_record('tag_instance', array('tagid'=>$tagid, 'itemtype'=>$record_type, 'itemid'=>$record_id, 'tiuserid'=>$userid), 'id')) {
00718         $tag_instance_object->ordering     = $ordering;
00719         $tag_instance_object->timemodified = time();
00720         return $DB->update_record('tag_instance', $tag_instance_object);
00721     } else {
00722         $tag_instance_object = new StdClass;
00723         $tag_instance_object->tagid        = $tagid;
00724         $tag_instance_object->itemid       = $record_id;
00725         $tag_instance_object->itemtype     = $record_type;
00726         $tag_instance_object->ordering     = $ordering;
00727         $tag_instance_object->timemodified = time();
00728         $tag_instance_object->tiuserid     = $userid;
00729         return $DB->insert_record('tag_instance', $tag_instance_object);
00730     }
00731 }
00732 
00739 function tag_autocomplete($text) {
00740     global $DB;
00741     return $DB->get_records_sql("SELECT tg.id, tg.name, tg.rawname
00742                                    FROM {tag} tg
00743                                   WHERE tg.name LIKE ?", array(moodle_strtolower($text)."%"));
00744 }
00745 
00754 function tag_cleanup() {
00755     global $DB;
00756 
00757     $instances = $DB->get_recordset('tag_instance');
00758 
00759     // cleanup tag instances
00760     foreach ($instances as $instance) {
00761         $delete = false;
00762 
00763         if (!$DB->record_exists('tag', array('id'=>$instance->tagid))) {
00764             // if the tag has been removed, instance should be deleted.
00765             $delete = true;
00766         } else {
00767             switch ($instance->itemtype) {
00768                 case 'user': // users are marked as deleted, but not actually deleted
00769                     if ($DB->record_exists('user', array('id'=>$instance->itemid, 'deleted'=>1))) {
00770                         $delete = true;
00771                     }
00772                     break;
00773                 default: // anything else, if the instance is not there, delete.
00774                     if (!$DB->record_exists($instance->itemtype, array('id'=>$instance->itemid))) {
00775                         $delete = true;
00776                     }
00777                     break;
00778             }
00779         }
00780         if ($delete) {
00781             tag_delete_instance($instance->itemtype, $instance->itemid, $instance->tagid);
00782             //debugging('deleting tag_instance #'. $instance->id .', linked to tag id #'. $instance->tagid, DEBUG_DEVELOPER);
00783         }
00784     }
00785     $instances->close();
00786 
00787     // TODO: this will only clean tags of type 'default'.  This is good as
00788     // it won't delete 'official' tags, but the day we get more than two
00789     // types, we need to fix this.
00790     $unused_tags = $DB->get_recordset_sql("SELECT tg.id
00791                                              FROM {tag} tg
00792                                             WHERE tg.tagtype = 'default'
00793                                                   AND NOT EXISTS (
00794                                                       SELECT 'x'
00795                                                         FROM {tag_instance} ti
00796                                                        WHERE ti.tagid = tg.id
00797                                                   )");
00798 
00799     // cleanup tags
00800     foreach ($unused_tags as $unused_tag) {
00801         tag_delete($unused_tag->id);
00802         //debugging('deleting unused tag #'. $unused_tag->id,  DEBUG_DEVELOPER);
00803     }
00804     $unused_tags->close();
00805 }
00806 
00823 function tag_compute_correlations($mincorrelation = 2) {
00824     global $DB;
00825 
00826     // This mighty one line query fetches a row from the database for every
00827     // individual tag correlation. We then need to process the rows collecting
00828     // the correlations for each tag id.
00829     // The fields used by this query are as follows:
00830     //   tagid         : This is the tag id, there should be at least $mincorrelation
00831     //                   rows for each tag id.
00832     //   correlation   : This is the tag id that correlates to the above tagid field.
00833     //   correlationid : This is the id of the row in the tag_correlation table that
00834     //                   relates to the tagid field and will be NULL if there are no
00835     //                   existing correlations
00836     $sql = 'SELECT pairs.tagid, pairs.correlation, pairs.ocurrences, co.id AS correlationid
00837               FROM (
00838                        SELECT ta.tagid, tb.tagid AS correlation, COUNT(*) AS ocurrences
00839                          FROM {tag_instance} ta
00840                          JOIN {tag_instance} tb ON (ta.itemtype = tb.itemtype AND ta.itemid = tb.itemid AND ta.tagid <> tb.tagid)
00841                      GROUP BY ta.tagid, tb.tagid
00842                        HAVING COUNT(*) > :mincorrelation
00843                    ) pairs
00844          LEFT JOIN {tag_correlation} co ON co.tagid = pairs.tagid
00845           ORDER BY pairs.tagid ASC, pairs.ocurrences DESC, pairs.correlation ASC';
00846     $rs = $DB->get_recordset_sql($sql, array('mincorrelation' => $mincorrelation));
00847 
00848     // Set up an empty tag correlation object
00849     $tagcorrelation = new stdClass;
00850     $tagcorrelation->id = null;
00851     $tagcorrelation->tagid = null;
00852     $tagcorrelation->correlatedtags = array();
00853 
00854     // We store each correlation id in this array so we can remove any correlations
00855     // that no longer exist.
00856     $correlations = array();
00857 
00858     // Iterate each row of the result set and build them into tag correlations.
00859     // We add all of a tag's correlations to $tagcorrelation->correlatedtags[]
00860     // then save the $tagcorrelation object
00861     foreach ($rs as $row) {
00862         if ($row->tagid != $tagcorrelation->tagid) {
00863             // The tag id has changed so we have all of the correlations for this tag
00864             $tagcorrelationid = tag_process_computed_correlation($tagcorrelation);
00865             if ($tagcorrelationid) {
00866                 $correlations[] = $tagcorrelationid;
00867             }
00868             // Now we reset the tag correlation object so we can reuse it and set it
00869             // up for the current record.
00870             $tagcorrelation = new stdClass;
00871             $tagcorrelation->id = $row->correlationid;
00872             $tagcorrelation->tagid = $row->tagid;
00873             $tagcorrelation->correlatedtags = array();
00874         }
00875         //Save the correlation on the tag correlation object
00876         $tagcorrelation->correlatedtags[] = $row->correlation;
00877     }
00878     // Update the current correlation after the last record.
00879     $tagcorrelationid = tag_process_computed_correlation($tagcorrelation);
00880     if ($tagcorrelationid) {
00881         $correlations[] = $tagcorrelationid;
00882     }
00883 
00884 
00885     // Close the recordset
00886     $rs->close();
00887 
00888     // Remove any correlations that weren't just identified
00889     if (empty($correlations)) {
00890         //there are no tag correlations
00891         $DB->delete_records('tag_correlation');
00892     } else {
00893         list($sql, $params) = $DB->get_in_or_equal($correlations, SQL_PARAMS_NAMED, 'param0000', false);
00894         $DB->delete_records_select('tag_correlation', 'id '.$sql, $params);
00895     }
00896 }
00897 
00908 function tag_process_computed_correlation(stdClass $tagcorrelation) {
00909     global $DB;
00910 
00911     // You must provide a tagid and correlatedtags must be set and be an array
00912     if (empty($tagcorrelation->tagid) || !isset($tagcorrelation->correlatedtags) || !is_array($tagcorrelation->correlatedtags)) {
00913         return false;
00914     }
00915 
00916     $tagcorrelation->correlatedtags = join(',', $tagcorrelation->correlatedtags);
00917     if (!empty($tagcorrelation->id)) {
00918         // The tag correlation already exists so update it
00919         $DB->update_record('tag_correlation', $tagcorrelation);
00920     } else {
00921         // This is a new correlation to insert
00922         $tagcorrelation->id = $DB->insert_record('tag_correlation', $tagcorrelation);
00923     }
00924     return $tagcorrelation->id;
00925 }
00926 
00930 function tag_cron() {
00931     tag_compute_correlations();
00932     tag_cleanup();
00933 }
00934 
00944 function tag_find_tags($text, $ordered=true, $limitfrom='', $limitnum='') {
00945     global $DB;
00946 
00947     $text = array_shift(tag_normalize($text, TAG_CASE_LOWER));
00948 
00949     if ($ordered) {
00950         $query = "SELECT tg.id, tg.name, tg.rawname, COUNT(ti.id) AS count
00951                     FROM {tag} tg LEFT JOIN {tag_instance} ti ON tg.id = ti.tagid
00952                    WHERE tg.name LIKE ?
00953                 GROUP BY tg.id, tg.name, tg.rawname
00954                 ORDER BY count DESC";
00955     } else {
00956         $query = "SELECT tg.id, tg.name, tg.rawname
00957                     FROM {tag} tg
00958                    WHERE tg.name LIKE ?";
00959     }
00960     $params = array("%{$text}%");
00961     return $DB->get_records_sql($query, $params, $limitfrom , $limitnum);
00962 }
00963 
00970 function tag_get_name($tagids) {
00971     global $DB;
00972 
00973     if (!is_array($tagids)) {
00974         if ($tag = $DB->get_record('tag', array('id'=>$tagids))) {
00975             return $tag->name;
00976         }
00977         return false;
00978     }
00979 
00980     $tag_names = array();
00981     foreach($DB->get_records_list('tag', 'id', $tagids) as $tag) {
00982         $tag_names[$tag->id] = $tag->name;
00983     }
00984 
00985     return $tag_names;
00986 }
00987 
00996 function tag_get_correlated($tag_id, $limitnum=null) {
00997     global $DB;
00998 
00999     $tag_correlation = $DB->get_record('tag_correlation', array('tagid'=>$tag_id));
01000 
01001     if (!$tag_correlation || empty($tag_correlation->correlatedtags)) {
01002         return array();
01003     }
01004 
01005     // this is (and has to) return the same fields as the query in tag_get_tags
01006     $sql = "SELECT DISTINCT tg.id, tg.tagtype, tg.name, tg.rawname, tg.flag, ti.ordering
01007               FROM {tag} tg
01008         INNER JOIN {tag_instance} ti ON tg.id = ti.tagid
01009              WHERE tg.id IN ({$tag_correlation->correlatedtags})";
01010     $result = $DB->get_records_sql($sql);
01011     if (!$result) {
01012         return array();
01013     }
01014 
01015     return $result;
01016 }
01017 
01027 function tag_normalize($rawtags, $case = TAG_CASE_LOWER) {
01028 
01029     // cache normalized tags, to prevent costly repeated calls to clean_param
01030     static $cleaned_tags_lc = array(); // lower case - use for comparison
01031     static $cleaned_tags_mc = array(); // mixed case - use for saving to database
01032 
01033     if ( !is_array($rawtags) ) {
01034         $rawtags = array($rawtags);
01035     }
01036 
01037     $result = array();
01038     foreach($rawtags as $rawtag) {
01039         $rawtag = trim($rawtag);
01040         if (!$rawtag) {
01041             continue;
01042         }
01043         if ( !array_key_exists($rawtag, $cleaned_tags_lc) ) {
01044             $cleaned_tags_lc[$rawtag] = moodle_strtolower( clean_param($rawtag, PARAM_TAG) );
01045             $cleaned_tags_mc[$rawtag] = clean_param($rawtag, PARAM_TAG);
01046         }
01047         if ( $case == TAG_CASE_LOWER ) {
01048             $result[$rawtag] = $cleaned_tags_lc[$rawtag];
01049         } else { // TAG_CASE_ORIGINAL
01050             $result[$rawtag] = $cleaned_tags_mc[$rawtag];
01051         }
01052     }
01053 
01054     return $result;
01055 }
01056 
01064 function tag_record_count($record_type, $tagid) {
01065     global $DB;
01066     return $DB->count_records('tag_instance', array('itemtype'=>$record_type, 'tagid'=>$tagid));
01067 }
01068 
01077 function tag_record_tagged_with($record_type, $record_id, $tag) {
01078     global $DB;
01079     if ($tagid = tag_get_id($tag)) {
01080         return $DB->count_records('tag_instance', array('itemtype'=>$record_type, 'itemid'=>$record_id, 'tagid'=>$tagid));
01081     } else {
01082         return 0; // tag doesn't exist
01083     }
01084 }
01085 
01092 function tag_set_flag($tagids) {
01093     global $DB;
01094 
01095     $tagids = (array)$tagids;
01096     foreach ($tagids as $tagid) {
01097         $tag = $DB->get_record('tag', array('id'=>$tagid), 'id, flag');
01098         $tag->flag++;
01099         $tag->timemodified = time();
01100         $DB->update_record('tag', $tag);
01101     }
01102 }
01103 
01110 function tag_unset_flag($tagids) {
01111     global $DB;
01112 
01113     if ( is_array($tagids) ) {
01114         $tagids = implode(',', $tagids);
01115     }
01116     $timemodified = time();
01117     return $DB->execute("UPDATE {tag} SET flag = 0, timemodified = ? WHERE id IN ($tagids)", array($timemodified));
01118 }
01119 
01120 
01127 function tag_page_type_list($pagetype, $parentcontext, $currentcontext) {
01128     return array(
01129         'tag-*'=>get_string('page-tag-x', 'tag'),
01130         'tag-index'=>get_string('page-tag-index', 'tag'),
01131         'tag-search'=>get_string('page-tag-search', 'tag'),
01132         'tag-manage'=>get_string('page-tag-manage', 'tag')
01133     );
01134 }
 All Data Structures Namespaces Files Functions Variables Enumerations