1f61105deSAdrian Lang<?php 2f61105deSAdrian Lang 30cfde7e9SMichael Großeif (!defined('DOKU_INC')) { 40cfde7e9SMichael Große die(); 50cfde7e9SMichael Große} 63496cc8aSAndreas Gohr 7e4543b6dSAdrian Langclass helper_plugin_tagging extends DokuWiki_Plugin { 8f61105deSAdrian Lang 9289f50bdSAndreas Gohr /** 10b12334e1SAndreas Gohr * Gives access to the database 11b12334e1SAndreas Gohr * 12b12334e1SAndreas Gohr * Initializes the SQLite helper and register the CLEANTAG function 13b12334e1SAndreas Gohr * 14b12334e1SAndreas Gohr * @return helper_plugin_sqlite|bool false if initialization fails 15289f50bdSAndreas Gohr */ 16289f50bdSAndreas Gohr public function getDB() { 17302a38efSAndreas Gohr static $db = null; 18f61105deSAdrian Lang if (!is_null($db)) { 19f61105deSAdrian Lang return $db; 20f61105deSAdrian Lang } 21f61105deSAdrian Lang 22302a38efSAndreas Gohr /** @var helper_plugin_sqlite $db */ 23f61105deSAdrian Lang $db = plugin_load('helper', 'sqlite'); 24f61105deSAdrian Lang if (is_null($db)) { 25f61105deSAdrian Lang msg('The tagging plugin needs the sqlite plugin', -1); 26f61105deSAdrian Lang return false; 27f61105deSAdrian Lang } 287e6afce6SAndreas Gohr $db->init('tagging', dirname(__FILE__) . '/db/'); 29302a38efSAndreas Gohr $db->create_function('CLEANTAG', array($this, 'cleanTag'), 1); 30f61105deSAdrian Lang return $db; 31f61105deSAdrian Lang } 32f61105deSAdrian Lang 33302a38efSAndreas Gohr /** 342ace74f4SAndreas Gohr * Return the user to use for accessing tags 352ace74f4SAndreas Gohr * 362ace74f4SAndreas Gohr * Handles the singleuser mode by returning 'auto' as user. Returnes false when no user is logged in. 372ace74f4SAndreas Gohr * 382ace74f4SAndreas Gohr * @return bool|string 392ace74f4SAndreas Gohr */ 402ace74f4SAndreas Gohr public function getUser() { 410cfde7e9SMichael Große if (!isset($_SERVER['REMOTE_USER'])) { 420cfde7e9SMichael Große return false; 430cfde7e9SMichael Große } 440cfde7e9SMichael Große if ($this->getConf('singleusermode')) { 450cfde7e9SMichael Große return 'auto'; 460cfde7e9SMichael Große } 472ace74f4SAndreas Gohr return $_SERVER['REMOTE_USER']; 482ace74f4SAndreas Gohr } 492ace74f4SAndreas Gohr 502ace74f4SAndreas Gohr /** 51302a38efSAndreas Gohr * Canonicalizes the tag to its lower case nospace form 52302a38efSAndreas Gohr * 53302a38efSAndreas Gohr * @param $tag 540cfde7e9SMichael Große * 55302a38efSAndreas Gohr * @return string 56302a38efSAndreas Gohr */ 57302a38efSAndreas Gohr public function cleanTag($tag) { 58302a38efSAndreas Gohr $tag = str_replace(' ', '', $tag); 5950547994SMichael Große $tag = str_replace('-', '', $tag); 6050547994SMichael Große $tag = str_replace('_', '', $tag); 61302a38efSAndreas Gohr $tag = utf8_strtolower($tag); 62302a38efSAndreas Gohr return $tag; 63302a38efSAndreas Gohr } 64302a38efSAndreas Gohr 6556d82720SAndreas Gohr /** 6656d82720SAndreas Gohr * Create or Update tags of a page 6756d82720SAndreas Gohr * 6856d82720SAndreas Gohr * Uses the translation plugin to store the language of a page (if available) 6956d82720SAndreas Gohr * 7056d82720SAndreas Gohr * @param string $id The page ID 7156d82720SAndreas Gohr * @param string $user 7256d82720SAndreas Gohr * @param array $tags 730cfde7e9SMichael Große * 7456d82720SAndreas Gohr * @return bool|SQLiteResult 7556d82720SAndreas Gohr */ 76f61105deSAdrian Lang public function replaceTags($id, $user, $tags) { 7756d82720SAndreas Gohr global $conf; 7856d82720SAndreas Gohr /** @var helper_plugin_translation $trans */ 7956d82720SAndreas Gohr $trans = plugin_load('helper', 'translation'); 8056d82720SAndreas Gohr if ($trans) { 8156d82720SAndreas Gohr $lang = $trans->realLC($trans->getLangPart($id)); 8256d82720SAndreas Gohr } else { 8356d82720SAndreas Gohr $lang = $conf['lang']; 8456d82720SAndreas Gohr } 8556d82720SAndreas Gohr 86f61105deSAdrian Lang $db = $this->getDB(); 87f61105deSAdrian Lang $db->query('BEGIN TRANSACTION'); 88f61105deSAdrian Lang $queries = array(array('DELETE FROM taggings WHERE pid = ? AND tagger = ?', $id, $user)); 89f61105deSAdrian Lang foreach ($tags as $tag) { 9056d82720SAndreas Gohr $queries[] = array('INSERT INTO taggings (pid, tagger, tag, lang) VALUES(?, ?, ?, ?)', $id, $user, $tag, $lang); 91f61105deSAdrian Lang } 92f61105deSAdrian Lang 93f61105deSAdrian Lang foreach ($queries as $query) { 94f61105deSAdrian Lang if (!call_user_func_array(array($db, 'query'), $query)) { 95f61105deSAdrian Lang $db->query('ROLLBACK TRANSACTION'); 96f61105deSAdrian Lang return false; 97f61105deSAdrian Lang } 98f61105deSAdrian Lang } 99f61105deSAdrian Lang return $db->query('COMMIT TRANSACTION'); 100f61105deSAdrian Lang } 101f61105deSAdrian Lang 1020a518a11SAndreas Gohr /** 103b12334e1SAndreas Gohr * Get a list of Tags or Pages matching search criteria 1040a518a11SAndreas Gohr * 105b12334e1SAndreas Gohr * @param array $filter What to search for array('field' => 'searchterm') 106b12334e1SAndreas Gohr * @param string $type What field to return 'tag'|'pid' 107077ff864SAndreas Gohr * @param int $limit Limit to this many results, 0 for all 1080cfde7e9SMichael Große * 1090a518a11SAndreas Gohr * @return array associative array in form of value => count 1100a518a11SAndreas Gohr */ 111077ff864SAndreas Gohr public function findItems($filter, $type, $limit = 0) { 112f61105deSAdrian Lang $db = $this->getDB(); 1130cfde7e9SMichael Große if (!$db) { 1140cfde7e9SMichael Große return array(); 1150cfde7e9SMichael Große } 116f61105deSAdrian Lang 117b12334e1SAndreas Gohr // create WHERE clause 118b12334e1SAndreas Gohr $where = '1=1'; 119b12334e1SAndreas Gohr foreach ($filter as $field => $value) { 120b12334e1SAndreas Gohr // compare clean tags only 121b12334e1SAndreas Gohr if ($field === 'tag') { 122b12334e1SAndreas Gohr $field = 'CLEANTAG(tag)'; 123b12334e1SAndreas Gohr $q = 'CLEANTAG(?)'; 124b12334e1SAndreas Gohr } else { 125b12334e1SAndreas Gohr $q = '?'; 126b12334e1SAndreas Gohr } 127204c069bSMichael Große 128204c069bSMichael Große if (substr($field, 0, 6) === 'notpid') { 129204c069bSMichael Große $field = 'pid'; 130204c069bSMichael Große 131204c069bSMichael Große // detect LIKE filters 132204c069bSMichael Große if ($this->useLike($value)) { 133204c069bSMichael Große $where .= " AND $field NOT LIKE $q"; 134204c069bSMichael Große } else { 135204c069bSMichael Große $where .= " AND $field != $q"; 136204c069bSMichael Große } 137204c069bSMichael Große } else { 138b12334e1SAndreas Gohr // detect LIKE filters 139b12334e1SAndreas Gohr if ($this->useLike($value)) { 140b12334e1SAndreas Gohr $where .= " AND $field LIKE $q"; 141b12334e1SAndreas Gohr } else { 142b12334e1SAndreas Gohr $where .= " AND $field = $q"; 143b12334e1SAndreas Gohr } 144b12334e1SAndreas Gohr } 145204c069bSMichael Große } 1466c37861bSJulian Einwag $where .= ' AND GETACCESSLEVEL(pid) >= ' . AUTH_READ; 14759a953ffSMichael Große 148b12334e1SAndreas Gohr // group and order 149b12334e1SAndreas Gohr if ($type == 'tag') { 150b12334e1SAndreas Gohr $groupby = 'CLEANTAG(tag)'; 151b12334e1SAndreas Gohr $orderby = 'CLEANTAG(tag)'; 152b12334e1SAndreas Gohr } else { 153b12334e1SAndreas Gohr $groupby = $type; 154466524f5SAndreas Gohr $orderby = "cnt DESC, $type"; 155b12334e1SAndreas Gohr } 156b12334e1SAndreas Gohr 157077ff864SAndreas Gohr // limit results 158077ff864SAndreas Gohr if ($limit) { 159077ff864SAndreas Gohr $limit = " LIMIT $limit"; 160077ff864SAndreas Gohr } else { 161077ff864SAndreas Gohr $limit = ''; 162077ff864SAndreas Gohr } 163077ff864SAndreas Gohr 164b12334e1SAndreas Gohr // create SQL 165b12334e1SAndreas Gohr $sql = "SELECT $type AS item, COUNT(*) AS cnt 166b12334e1SAndreas Gohr FROM taggings 167b12334e1SAndreas Gohr WHERE $where 168b12334e1SAndreas Gohr GROUP BY $groupby 169077ff864SAndreas Gohr ORDER BY $orderby 170077ff864SAndreas Gohr $limit 171077ff864SAndreas Gohr "; 172b12334e1SAndreas Gohr 173b12334e1SAndreas Gohr // run query and turn into associative array 174b12334e1SAndreas Gohr $res = $db->query($sql, array_values($filter)); 175f61105deSAdrian Lang $res = $db->res2arr($res); 176b12334e1SAndreas Gohr 177f61105deSAdrian Lang $ret = array(); 178b12334e1SAndreas Gohr foreach ($res as $row) { 179b12334e1SAndreas Gohr $ret[$row['item']] = $row['cnt']; 180f61105deSAdrian Lang } 181f61105deSAdrian Lang return $ret; 182f61105deSAdrian Lang } 183f61105deSAdrian Lang 184b12334e1SAndreas Gohr /** 185b12334e1SAndreas Gohr * Check if the given string is a LIKE statement 186b12334e1SAndreas Gohr * 187b12334e1SAndreas Gohr * @param string $value 1880cfde7e9SMichael Große * 189b12334e1SAndreas Gohr * @return bool 190b12334e1SAndreas Gohr */ 191b12334e1SAndreas Gohr private function useLike($value) { 192b12334e1SAndreas Gohr return strpos($value, '%') === 0 || strrpos($value, '%') === strlen($value) - 1; 193b2073787SDominik Eckelmann } 194b2073787SDominik Eckelmann 195302a38efSAndreas Gohr /** 196302a38efSAndreas Gohr * Constructs the URL to search for a tag 197302a38efSAndreas Gohr * 1985540f91dSAndreas Gohr * @param string $tag 1995540f91dSAndreas Gohr * @param string $ns 2000cfde7e9SMichael Große * 201302a38efSAndreas Gohr * @return string 202302a38efSAndreas Gohr */ 2035540f91dSAndreas Gohr public function getTagSearchURL($tag, $ns = '') { 204bed9f360SAndreas Gohr // wrap tag in quotes if non clean 2052cb25ec1SAndreas Gohr $ctag = utf8_stripspecials($this->cleanTag($tag)); 2060cfde7e9SMichael Große if ($ctag != utf8_strtolower($tag)) { 2070cfde7e9SMichael Große $tag = '"' . $tag . '"'; 2080cfde7e9SMichael Große } 209bed9f360SAndreas Gohr 210bed9f360SAndreas Gohr $ret = '?do=search&id=' . rawurlencode($tag); 2110cfde7e9SMichael Große if ($ns) { 2120cfde7e9SMichael Große $ret .= rawurlencode(' @' . $ns); 2130cfde7e9SMichael Große } 2145540f91dSAndreas Gohr 2155540f91dSAndreas Gohr return $ret; 216f61105deSAdrian Lang } 217f61105deSAdrian Lang 2185540f91dSAndreas Gohr /** 2195540f91dSAndreas Gohr * Calculates the size levels for the given list of clouds 2205540f91dSAndreas Gohr * 2215540f91dSAndreas Gohr * Automatically determines sensible tresholds 2225540f91dSAndreas Gohr * 2235540f91dSAndreas Gohr * @param array $tags list of tags => count 2245540f91dSAndreas Gohr * @param int $levels 2250cfde7e9SMichael Große * 2265540f91dSAndreas Gohr * @return mixed 2275540f91dSAndreas Gohr */ 228f61105deSAdrian Lang public function cloudData($tags, $levels = 10) { 229f61105deSAdrian Lang $min = min($tags); 230f61105deSAdrian Lang $max = max($tags); 231f61105deSAdrian Lang 232f61105deSAdrian Lang // calculate tresholds 233f61105deSAdrian Lang $tresholds = array(); 234f61105deSAdrian Lang for ($i = 0; $i <= $levels; $i++) { 235f61105deSAdrian Lang $tresholds[$i] = pow($max - $min + 1, $i / $levels) + $min - 1; 236f61105deSAdrian Lang } 237f61105deSAdrian Lang 238f61105deSAdrian Lang // assign weights 239f61105deSAdrian Lang foreach ($tags as $tag => $cnt) { 240f61105deSAdrian Lang foreach ($tresholds as $tresh => $val) { 241f61105deSAdrian Lang if ($cnt <= $val) { 242f61105deSAdrian Lang $tags[$tag] = $tresh; 243f61105deSAdrian Lang break; 244f61105deSAdrian Lang } 245f61105deSAdrian Lang $tags[$tag] = $levels; 246f61105deSAdrian Lang } 247f61105deSAdrian Lang } 248f61105deSAdrian Lang return $tags; 249f61105deSAdrian Lang } 250f61105deSAdrian Lang 2515540f91dSAndreas Gohr /** 2525540f91dSAndreas Gohr * Display a tag cloud 2535540f91dSAndreas Gohr * 2545540f91dSAndreas Gohr * @param array $tags list of tags => count 2555540f91dSAndreas Gohr * @param string $type 'tag' 2565540f91dSAndreas Gohr * @param Callable $func The function to print the link (gets tag and ns) 2575540f91dSAndreas Gohr * @param bool $wrap wrap cloud in UL tags? 2585540f91dSAndreas Gohr * @param bool $return returnn HTML instead of printing? 2595540f91dSAndreas Gohr * @param string $ns Add this namespace to search links 2600cfde7e9SMichael Große * 2615540f91dSAndreas Gohr * @return string 2625540f91dSAndreas Gohr */ 2635540f91dSAndreas Gohr public function html_cloud($tags, $type, $func, $wrap = true, $return = false, $ns = '') { 264a66f6715SAndreas Gohr global $INFO; 265a66f6715SAndreas Gohr 266a66f6715SAndreas Gohr $hidden_str = $this->getConf('hiddenprefix'); 267a66f6715SAndreas Gohr $hidden_len = strlen($hidden_str); 268a66f6715SAndreas Gohr 269f61105deSAdrian Lang $ret = ''; 2700cfde7e9SMichael Große if ($wrap) { 2710cfde7e9SMichael Große $ret .= '<ul class="tagging_cloud clearfix">'; 2720cfde7e9SMichael Große } 273f61105deSAdrian Lang if (count($tags) === 0) { 274f61105deSAdrian Lang // Produce valid XHTML (ul needs a child) 275f61105deSAdrian Lang $this->setupLocale(); 276f61105deSAdrian Lang $ret .= '<li><div class="li">' . $this->lang['js']['no' . $type . 's'] . '</div></li>'; 277f61105deSAdrian Lang } else { 278f61105deSAdrian Lang $tags = $this->cloudData($tags); 279f61105deSAdrian Lang foreach ($tags as $val => $size) { 280a66f6715SAndreas Gohr // skip hidden tags for users that can't edit 281a66f6715SAndreas Gohr if ($type == 'tag' and 282a66f6715SAndreas Gohr $hidden_len and 283a66f6715SAndreas Gohr substr($val, 0, $hidden_len) == $hidden_str and 284a66f6715SAndreas Gohr !($this->getUser() && $INFO['writable']) 285a66f6715SAndreas Gohr ) { 286a66f6715SAndreas Gohr continue; 287a66f6715SAndreas Gohr } 288a66f6715SAndreas Gohr 289f61105deSAdrian Lang $ret .= '<li class="t' . $size . '"><div class="li">'; 2905540f91dSAndreas Gohr $ret .= call_user_func($func, $val, $ns); 291f61105deSAdrian Lang $ret .= '</div></li>'; 292f61105deSAdrian Lang } 293f61105deSAdrian Lang } 2940cfde7e9SMichael Große if ($wrap) { 2950cfde7e9SMichael Große $ret .= '</ul>'; 2960cfde7e9SMichael Große } 2970cfde7e9SMichael Große if ($return) { 2980cfde7e9SMichael Große return $ret; 2990cfde7e9SMichael Große } 300f61105deSAdrian Lang echo $ret; 3015540f91dSAndreas Gohr return ''; 302f61105deSAdrian Lang } 303f61105deSAdrian Lang 3045540f91dSAndreas Gohr /** 3055540f91dSAndreas Gohr * Get the link to a search for the given tag 3065540f91dSAndreas Gohr * 3075540f91dSAndreas Gohr * @param string $tag search for this tag 3085540f91dSAndreas Gohr * @param string $ns limit search to this namespace 3090cfde7e9SMichael Große * 3105540f91dSAndreas Gohr * @return string 3115540f91dSAndreas Gohr */ 3125540f91dSAndreas Gohr protected function linkToSearch($tag, $ns = '') { 3135540f91dSAndreas Gohr return '<a href="' . hsc($this->getTagSearchURL($tag, $ns)) . '">' . $tag . '</a>'; 314f61105deSAdrian Lang } 315f61105deSAdrian Lang 316fb1d0583SAndreas Gohr /** 317fb1d0583SAndreas Gohr * Display the Tags for the current page and prepare the tag editing form 3183496cc8aSAndreas Gohr * 3193496cc8aSAndreas Gohr * @param bool $print Should the HTML be printed or returned? 3200cfde7e9SMichael Große * 3213496cc8aSAndreas Gohr * @return string 322fb1d0583SAndreas Gohr */ 3233496cc8aSAndreas Gohr public function tpl_tags($print = true) { 324f61105deSAdrian Lang global $INFO; 325f61105deSAdrian Lang global $lang; 3263bf0e2f1SMichael Große 3273bf0e2f1SMichael Große $filter = array('pid' => $INFO['id']); 3283bf0e2f1SMichael Große if ($this->getConf('singleusermode')) { 3293bf0e2f1SMichael Große $filter['tagger'] = 'auto'; 3303bf0e2f1SMichael Große } 3313bf0e2f1SMichael Große 3323bf0e2f1SMichael Große $tags = $this->findItems($filter, 'tag'); 3333496cc8aSAndreas Gohr 3343496cc8aSAndreas Gohr $ret = ''; 3353496cc8aSAndreas Gohr 3363496cc8aSAndreas Gohr $ret .= '<div class="plugin_tagging_edit">'; 3373496cc8aSAndreas Gohr $ret .= $this->html_cloud($tags, 'tag', array($this, 'linkToSearch'), true, true); 338f61105deSAdrian Lang 3392ace74f4SAndreas Gohr if ($this->getUser() && $INFO['writable']) { 340f61105deSAdrian Lang $lang['btn_tagging_edit'] = $lang['btn_secedit']; 3413496cc8aSAndreas Gohr $ret .= html_btn('tagging_edit', $INFO['id'], '', array()); 342*2819ffcdSSzymon Olewniczak 343*2819ffcdSSzymon Olewniczak $form = new dokuwiki\Form\Form(); 344*2819ffcdSSzymon Olewniczak $form->id('tagging__edit'); 345*2819ffcdSSzymon Olewniczak $form->setHiddenField('tagging[id]', $INFO['id']); 346*2819ffcdSSzymon Olewniczak $form->setHiddenField('call', 'plugin_tagging_save'); 347*2819ffcdSSzymon Olewniczak $tags = $this->findItems(array( 348*2819ffcdSSzymon Olewniczak 'pid' => $INFO['id'], 349*2819ffcdSSzymon Olewniczak 'tagger' => $this->getUser() 350*2819ffcdSSzymon Olewniczak ), 'tag'); 351*2819ffcdSSzymon Olewniczak $form->addTextInput('tagging[tags]')->val(implode(', ', array_keys($tags)))->addClass('edit'); 352*2819ffcdSSzymon Olewniczak $form->addButton('do[save]', $lang['btn_save'])->id('tagging__edit_save'); 353*2819ffcdSSzymon Olewniczak $form->addButton('do[cancel]', $lang['btn_cancel'])->id('tagging__edit_cancel'); 354*2819ffcdSSzymon Olewniczak $ret .= $form->toHTML(); 355f61105deSAdrian Lang } 3563496cc8aSAndreas Gohr $ret .= '</div>'; 3573496cc8aSAndreas Gohr 3580cfde7e9SMichael Große if ($print) { 3590cfde7e9SMichael Große echo $ret; 3600cfde7e9SMichael Große } 3613496cc8aSAndreas Gohr return $ret; 362f61105deSAdrian Lang } 363872edc7cSRené Corinth 3648a1a3846SAndreas Gohr /** 3658a1a3846SAndreas Gohr * @return array 3668a1a3846SAndreas Gohr */ 367872edc7cSRené Corinth public function getAllTags() { 368872edc7cSRené Corinth 369872edc7cSRené Corinth $db = $this->getDb(); 3708a1a3846SAndreas Gohr $res = $db->query('SELECT pid, tag, tagger FROM taggings ORDER BY tag'); 371872edc7cSRené Corinth 372872edc7cSRené Corinth $tags_tmp = $db->res2arr($res); 373872edc7cSRené Corinth $tags = array(); 374872edc7cSRené Corinth foreach ($tags_tmp as $tag) { 375302a38efSAndreas Gohr $tid = $this->cleanTag($tag['tag']); 376872edc7cSRené Corinth 3770cfde7e9SMichael Große if (!isset($tags[$tid]['orig'])) { 3780cfde7e9SMichael Große $tags[$tid]['orig'] = array(); 3790cfde7e9SMichael Große } 380fb1d0583SAndreas Gohr $tags[$tid]['orig'][] = $tag['tag']; 381872edc7cSRené Corinth 382302a38efSAndreas Gohr if (isset($tags[$tid]['count'])) { 383302a38efSAndreas Gohr $tags[$tid]['count']++; 384302a38efSAndreas Gohr $tags[$tid]['tagger'][] = $tag['tagger']; 385872edc7cSRené Corinth } else { 386302a38efSAndreas Gohr $tags[$tid]['count'] = 1; 387302a38efSAndreas Gohr $tags[$tid]['tagger'] = array($tag['tagger']); 388872edc7cSRené Corinth } 389872edc7cSRené Corinth } 390872edc7cSRené Corinth return $tags; 391872edc7cSRené Corinth } 392872edc7cSRené Corinth 3938a1a3846SAndreas Gohr /** 3948a1a3846SAndreas Gohr * Renames a tag 3958a1a3846SAndreas Gohr * 3968a1a3846SAndreas Gohr * @param string $formerTagName 3978a1a3846SAndreas Gohr * @param string $newTagName 3988a1a3846SAndreas Gohr */ 399872edc7cSRené Corinth public function renameTag($formerTagName, $newTagName) { 400872edc7cSRené Corinth 401872edc7cSRené Corinth if (empty($formerTagName) || empty($newTagName)) { 4028a1a3846SAndreas Gohr msg($this->getLang("admin enter tag names"), -1); 4038a1a3846SAndreas Gohr return; 404872edc7cSRené Corinth } 405872edc7cSRené Corinth 406872edc7cSRené Corinth $db = $this->getDb(); 407872edc7cSRené Corinth 408fb1d0583SAndreas Gohr $res = $db->query('SELECT pid FROM taggings WHERE CLEANTAG(tag) = ?', $this->cleanTag($formerTagName)); 409872edc7cSRené Corinth $check = $db->res2arr($res); 410872edc7cSRené Corinth 411872edc7cSRené Corinth if (empty($check)) { 4128a1a3846SAndreas Gohr msg($this->getLang("admin tag does not exists"), -1); 4138a1a3846SAndreas Gohr return; 414872edc7cSRené Corinth } 415872edc7cSRené Corinth 416fb1d0583SAndreas Gohr $res = $db->query("UPDATE taggings SET tag = ? WHERE CLEANTAG(tag) = ?", $newTagName, $this->cleanTag($formerTagName)); 417872edc7cSRené Corinth $db->res2arr($res); 418872edc7cSRené Corinth 419fb1d0583SAndreas Gohr msg($this->getLang("admin renamed"), 1); 4208a1a3846SAndreas Gohr return; 421872edc7cSRené Corinth } 422872edc7cSRené Corinth 423f61105deSAdrian Lang} 424