add('name', PLUGIN_EVENT_FREETAG_TITLE); $propbag->add('description', PLUGIN_EVENT_FREETAG_DESC); $propbag->add('stackable', false); $propbag->add('author', 'Garvin Hicking, Jonathan Arkell, Grischa Brockhaus, Lars Strojny, Malte Paskuda, Ian'); $propbag->add('requirements', array( 'serendipity' => '1.3', 'smarty' => '2.6.7', 'php' => '7.0' )); $propbag->add('version', '3.70.3'); $propbag->add('event_hooks', array( 'frontend_fetchentries' => true, 'frontend_fetchentry' => true, 'frontend_display:rss-2.0:per_entry' => true, 'frontend_header' => true, // 'frontend_display:rss-0.92:per_entry' => true, 'frontend_display:rss-1.0:per_entry' => true, // 'frontend_display:rss-0.91:per_entry' => true, 'frontend_display:atom-0.3:per_entry' => true, 'frontend_display:atom-1.0:per_entry' => true, 'frontend_entryproperties' => true, 'frontend_rss' => true, 'entry_display' => true, 'entries_header' => true, 'backend_publish' => true, 'backend_save' => true, 'backend_display' => true, 'backend_sidebar_entries' => true, 'backend_sidebar_entries_event_display_managetags' => true, 'backend_delete_entry' => true, 'external_plugin' => true, 'xmlrpc_updertEntry' => true, 'xmlrpc_fetchEntry' => true, 'xmlrpc_deleteEntry' => true, 'css' => true, 'css_backend' => true, 'js_backend' => true )); $propbag->add('groups', array('BACKEND_EDITOR')); $this->supported_properties = array('freetag_name', 'freetag_tagList'); $this->dependencies = array('serendipity_plugin_freetag' => 'keep'); $propbag->add('configuration', array('cat2tag', 'keyword2tag', 'taglink', 'taglist', 'embed_footer', 'extended_smarty', 'show_tagcloud', 'min_percent', 'max_percent', 'max_tags', 'use_flash', 'flash_tag_color', 'flash_bg_trans', 'flash_bg_color', 'flash_width', 'flash_speed', 'meta_keywords', 'show_related', 'show_related_count', 'lowercase_tags', 'collation', 'send_http_header', 'admin_show_taglist', 'admin_ftayt', 'technorati_tag_link', 'technorati_tag_image')); } function introspect_config_item($name, &$propbag) { global $serendipity; switch($name) { case 'show_tagcloud': $propbag->add('type', 'boolean'); $propbag->add('name', PLUGIN_EVENT_FREETAG_SHOW_TAGCLOUD); $propbag->add('description', ''); $propbag->add('default', true); break; case 'cat2tag': $propbag->add('type', 'boolean'); $propbag->add('name', PLUGIN_EVENT_FREETAG_CAT2TAG); $propbag->add('description', PLUGIN_EVENT_FREETAG_CAT2TAG_DESC); $propbag->add('default', false); break; case 'keyword2tag': $propbag->add('type', 'boolean'); $propbag->add('name', PLUGIN_EVENT_FREETAG_KEYWORD2TAG); $propbag->add('description', PLUGIN_EVENT_FREETAG_KEYWORD2TAG_DESC); $propbag->add('default', false); break; case 'embed_footer': $propbag->add('type', 'select'); $propbag->add('name', PLUGIN_EVENT_FREETAG_EMBED_FOOTER); $propbag->add('description', PLUGIN_EVENT_FREETAG_EMBED_FOOTER_DESC . ' ' . PLUGIN_EVENT_FREETAG_EMBED_FOOTER_DESC2); $propbag->add('select_values', array( 'yes' => YES, 'no' => NO, 'smarty' => 'Smarty' )); $propbag->add('default', 'true'); break; case 'extended_smarty': $propbag->add('type', 'boolean'); $propbag->add('name', PLUGIN_EVENT_FREETAG_EXTENDED_SMARTY); $propbag->add('description', PLUGIN_EVENT_FREETAG_EXTENDED_SMARTY_DESC); $propbag->add('default', false); break; case 'taglist': $propbag->add('type', 'boolean'); $propbag->add('name', PLUGIN_EVENT_FREETAG_TAGSASLIST); $propbag->add('description', PLUGIN_EVENT_FREETAG_TAGSASLIST_DESC); $propbag->add('default', false); break; case 'taglink': $propbag->add('type', 'string'); $propbag->add('name', PLUGIN_EVENT_FREETAG_TAGLINK); $propbag->add('description', PLUGIN_EVENT_FREETAG_TAGLINK_DESC); $propbag->add('default', $serendipity['baseURL'] . ($serendipity['rewrite'] == 'none' ? $serendipity['indexFile'] . '?/' : '') . 'plugin/tag/'); break; case 'min_percent': $propbag->add('type', 'string'); $propbag->add('name', PLUGIN_EVENT_FREETAG_TAGCLOUD_MIN); $propbag->add('description', ''); $propbag->add('default', '100'); break; case 'max_percent': $propbag->add('type', 'string'); $propbag->add('name', PLUGIN_EVENT_FREETAG_TAGCLOUD_MAX); $propbag->add('description', ''); $propbag->add('default', '300'); break; case 'collation': $propbag->add('type', 'string'); $propbag->add('name', PLUGIN_EVENT_FREETAG_COLLATION); $propbag->add('description', ''); $propbag->add('default', ''); break; case 'max_tags': $propbag->add('type', 'string'); $propbag->add('name', PLUGIN_FREETAG_MAX_TAGS); $propbag->add('description', ''); $propbag->add('default', '45'); break; case 'meta_keywords': $propbag->add('type', 'string'); $propbag->add('name', PLUGIN_FREETAG_META_KEYWORDS); $propbag->add('description', ''); $propbag->add('default', '0'); break; case 'show_related': $propbag->add('type', 'boolean'); $propbag->add('name', PLUGIN_EVENT_FREETAG_SHOW_RELATED); $propbag->add('description', ''); $propbag->add('default', true); break; case 'show_related_count': $propbag->add('type', 'string'); $propbag->add('name', PLUGIN_EVENT_FREETAG_SHOW_RELATED_COUNT); $propbag->add('description', ''); $propbag->add('default', '5'); break; case 'lowercase_tags': $propbag->add('type', 'boolean'); $propbag->add('name', PLUGIN_EVENT_FREETAG_LOWERCASE_TAGS); $propbag->add('description', ''); $propbag->add('default', true); break; case 'send_http_header': $propbag->add('type', 'boolean'); $propbag->add('name', PLUGIN_EVENT_FREETAG_SEND_HTTP_HEADER); $propbag->add('description', ''); $propbag->add('default', true); break; case 'admin_show_taglist': $propbag->add('type', 'boolean'); $propbag->add('name', PLUGIN_EVENT_FREETAG_ADMIN_TAGLIST); $propbag->add('description', ''); $propbag->add('default', true); break; case 'admin_ftayt': $propbag->add('type', 'boolean'); $propbag->add('name', PLUGIN_EVENT_FREETAG_ADMIN_FTAYT); $propbag->add('description', ''); $propbag->add('default', false); break; case 'technorati_tag_link': $propbag->add('type', 'boolean'); $propbag->add('name', PLUGIN_EVENT_FREETAG_TECHNORATI_TAGLINK); $propbag->add('description', PLUGIN_EVENT_FREETAG_TECHNORATI_TAGLINK_DESC); $propbag->add('default', false); break; case 'technorati_tag_image': $propbag->add('type', 'string'); $propbag->add('name', PLUGIN_EVENT_FREETAG_TECHNORATI_TAGLINK_IMG); $propbag->add('description', ''); $propbag->add('default', 'http://static.technorati.com/static/img/pub/icon-utag-16x13.png'); break; case 'use_flash': $propbag->add('type', 'boolean'); $propbag->add('name', PLUGIN_EVENT_FREETAG_USE_FLASH); $propbag->add('description', ''); $propbag->add('default', false); break; case 'flash_bg_trans': $propbag->add('type', 'boolean'); $propbag->add('name', PLUGIN_EVENT_FREETAG_FLASH_TRANSPARENT); $propbag->add('description', ''); $propbag->add('default', false); break; case 'flash_tag_color': $propbag->add('type', 'string'); $propbag->add('name', PLUGIN_EVENT_FREETAG_FLASH_TAG_COLOR); $propbag->add('description', ''); $propbag->add('default', 'ff6600'); break; case 'flash_bg_color': $propbag->add('type', 'string'); $propbag->add('name', PLUGIN_EVENT_FREETAG_FLASH_BG_COLOR); $propbag->add('description', ''); $propbag->add('default', 'ffffff'); break; case 'flash_width': $propbag->add('type', 'string'); $propbag->add('name', PLUGIN_EVENT_FREETAG_FLASH_WIDTH); $propbag->add('description', ''); $propbag->add('default', '500'); break; case 'flash_speed': $propbag->add('type', 'string'); $propbag->add('name', PLUGIN_EVENT_FREETAG_FLASH_SPEED); $propbag->add('description', ''); $propbag->add('default', '100'); break; } return true; } function generate_content(&$title) { $title = $this->title; } static function tableCreated($table = 'entrytags') { global $serendipity; try { $q = "select count(tag) from {$serendipity['dbPrefix']}" . $table; $row = serendipity_db_query($q, true, 'num'); } catch (exception $e) { return false; } if (!is_numeric($row[0])) { // if the response we got back was an SQL error.. :P return false; } else { return true; } } static function upgradeFromVersion1() { global $serendipity; $q = "SELECT count(*) FROM {$serendipity['dbPrefix']}entryproperties WHERE property = 'ep_freetag_name'"; $result = serendipity_db_query($q); if ((int)$result[0] > 0) { return true; } else { return false; } } static function convertEntryPropertiesTags() { global $serendipity; $q = "SELECT entryid, value FROM {$serendipity['dbPrefix']}entryproperties WHERE property = 'ep_freetag_name'"; $result = serendipity_db_query($q); if (!is_array($result)) { return false; } foreach($result as $entry) { $tags = serendipity_event_freetag::makeTagsFromTaglist($entry['value']); serendipity_event_freetag::addTagsToEntry($entry['entryid'], $tags); printf(PLUGIN_FREETAG_UPGRADE1_2, count($tags), $entry['entryid']); echo '
'; } $q = "DELETE FROM {$serendipity['dbPrefix']}entryproperties WHERE property = 'ep_freetag_name'"; $result = serendipity_db_query($q); } function cleanup() { global $serendipity; serendipity_event_freetag::static_install(); } function install() { serendipity_event_freetag::static_install(); } static function static_install() { global $serendipity; if (!serendipity_event_freetag::tableCreated('entrytags')) { $q = "CREATE TABLE {$serendipity['dbPrefix']}entrytags (" . "entryid int(10) not null, " . "tag varchar(50) not null, " . "primary key (entryid, tag)" . ")"; $result = serendipity_db_schema_import($q); if ($result !== true) { return; } serendipity_db_schema_import("CREATE INDEX tagsentryindex ON {$serendipity['dbPrefix']}entrytags (entryid)"); serendipity_db_schema_import("CREATE INDEX tagsTagIndex ON {$serendipity['dbPrefix']}entrytags (tag)"); } if (!serendipity_event_freetag::tableCreated('tagkeywords')) { $q = "CREATE TABLE {$serendipity['dbPrefix']}tagkeywords (" . "keywords text, " . "tag varchar(50) not null, " . "primary key (tag)" . ")"; $result = serendipity_db_schema_import($q); } if (serendipity_event_freetag::upgradeFromVersion1()) { serendipity_event_freetag::convertEntryPropertiesTags(); } else { echo "NOT UPGRADING!"; } } static function makeURLTag($tag) { return str_replace('.', '%FF', urlencode($tag)); } function getTagHtmlFromCSV($tagString) { global $serendipity; static $taglink = null; if ($taglink == null) { $taglink = $this->get_config('taglink'); } $links = array(); if (empty($tagString)) { return array(); } $tags = explode(',', $tagString); foreach($tags as $tag) { $tag = trim($tag); if (empty($tag)) { continue; } $links[] = ''; } return implode(', ', $links); } function getTagHtml($tags, $extended_smarty = false) { global $serendipity; static $taglink = null; $links = array(); if ($taglink == null) { $taglink = $this->get_config('taglink'); } if (!is_array($tags)) { return ''; } $technorati = $this->get_config('technorati_tag_link'); $technorati_img = $this->get_config('technorati_tag_image'); $img_url = $this->get_config('path_img',$serendipity['serendipityHTTPPath'] . 'plugins/serendipity_event_freetag/img/'); foreach($tags as $tag) { $tag = trim($tag); if (empty($tag)) { continue; } $links[] = '' . ($technorati?'':''); } if ($extended_smarty) { return $links; } else { return implode(', ', $links); } } function getRelatedEntries($tags, $postID) { global $serendipity; if (!is_array($tags)) { return false; } foreach($tags AS $idx => $tag) { $tags[$idx] = serendipity_db_escape_string($tag); } $q = "SELECT DISTINCT e1.entryid, e2.title, e2.timestamp FROM {$serendipity['dbPrefix']}entrytags AS e1 LEFT JOIN {$serendipity['dbPrefix']}entries AS e2 ON e1.entryid = e2.id WHERE e1.tag IN ('" . implode("', '", $tags) . "') AND e1.entryid != " . (int)$postID . " AND e2.isdraft = 'false' " . (!serendipity_db_bool($serendipity['showFutureEntries']) ? " AND e2.timestamp <= " . time() : '') . " ORDER BY e2.timestamp DESC LIMIT " . $this->get_config('show_related_count', 10); $result = serendipity_db_query($q, false, 'assoc', false, 'entryid', 'title'); if (!is_array($result)) { return false; } return $result; } function getRelatedEntriesHtml(&$entries, $extended_smarty = false) { global $serendipity; if (!is_array($entries)) { return false; } $entrylink = $serendipity['baseURL'] . ($serendipity['rewrite'] == 'none' ? $serendipity['indexFile'] . '?/' : '/'); if ($extended_smarty) { $return = array(); $return['description'] = PLUGIN_EVENT_FREETAG_RELATED_ENTRIES; foreach($entries AS $entryid => $title) { $return['entries'][] = '' . (function_exists('serendipity_specialchars') ? serendipity_specialchars($title) : htmlspecialchars($title, ENT_COMPAT, LANG_CHARSET)) . ''; } } else { $return = ''; } return $return; } /* This method can be called statically. Tags should be an array with the key being the tag name, and val being the number of occurances. */ static function displayTags($tags, $xml, $nl, $scaling, $maxSize = 200, $minSize = 100, $useFlash = false, $flashbgtrans = true, $flashtagcolor = 'ff6600', $flashbgcolor = 'ffffff', $flashwidth = 190, $flashspeed = 100, $cfg_taglink = null, $cfg_template = null, $xml_image = 'img/xml.gif') { global $serendipity; if (!is_array($tags)) { return false; } static $taglink = null; if ($taglink == null) { $taglink = $cfg_taglink; } $template = $cfg_template; if (!$template) { serendipity_event_freetag::renderTags($tags, $xml, $nl, $scaling, $maxSize, $minSize, $useFlash, $flashbgtrans, $flashtagcolor, $flashbgcolor, $flashwidth, $flashspeed, $taglink, $xml_image); } else { arsort($tags); $tagsWithLinks = array(); foreach ($tags as $tag => $count) { $tagsWithLinks[$tag] = array( 'count' => $count, 'href' => $taglink . serendipity_event_freetag::makeUrlTag($tag), ); } $serendipity['smarty']->assign('tags', $tagsWithLinks); $template = serendipity_getTemplateFile($template, 'serendipityPath'); $serendipity['smarty']->display($template); } return true; } static function renderTags($tags, $xml, $nl, $scaling, $maxSize, $minSize, $useFlash, $flashbgtrans, $flashtagcolor, $flashbgcolor, $flashwidth, $flashspeed, $taglink, $xml_image = 'img/xml.gif') { global $serendipity; $rsslink = $serendipity['serendipityHTTPPath'] . 'rss.php?serendipity%5Btag%5D='; $xmlImg = serendipity_getTemplateFile($xml_image); $first = true; $biggest = max($tags); $smallest= min($tags); $scale = $biggest - $smallest; if ($scale < 0) { $scale = 1; } $key = uniqid(rand()); if ($useFlash) { echo '
'. "\n"; echo "\n". ''. "\n"; echo ''. "\n"; echo ''. "\n"; echo ' '; } if ($scaling) { if ($scale==0) { $fontSize = $maxSize; } elseif ($scale==1) { if ($quantity==$biggest) { $fontSize = $maxSize; } else { $fontSize = $minSize; } } else { $fontSize = round(($quantity - $smallest)*(($maxSize - $minSize)/($scale))) + $minSize; } $html .= ''; } else { $fontSize = 100; } $html .= ''; if ($scaling) { $html .= ''; } if ($xml) { $html .= ""; } if ($nl) { $html .= '
' . "\n"; } $first = false; $tagparam .= "%3Ca href='" . $taglink . serendipity_event_freetag::makeURLTag($name) . "' style='" . round($fontSize/5) . "'%3E" . str_replace(' ',' ',(function_exists('serendipity_specialchars') ? serendipity_specialchars($name) : htmlspecialchars($name, ENT_COMPAT, LANG_CHARSET))) . "%3C/a%3E"; } if ($useFlash) { echo $tagparam; echo '%3C/tags%3E" />' . "\n"; echo '' . "\n"; echo "\n" . ''. "\n"; echo '' . "\n"; echo ''. "\n"; echo ''. "\n"; } echo $html; if ($useFlash) { echo ''. "\n"; echo ''. "\n"; echo ''. "\n"; echo '
'. "\n"; echo '
'. "\n"; } } function event_hook($event, &$bag, &$eventData, $addData = null) { global $serendipity; $hooks = &$bag->get('event_hooks'); if (isset($hooks[$event])) { switch($event) { case 'backend_delete_entry': $this->deleteTagsForEntry((int)$eventData); return true; case 'frontend_header': if (serendipity_db_bool($this->get_config('use_flash'))) { echo ''. "\n"; echo ''. "\n"; } $this->displayMetaKeywords($serendipity['GET']['id'] ?? null, $this->displayTag ); return true; case 'frontend_display:rss-2.0:per_entry': case 'frontend_display:rss-0.91:per_entry': $eventData['display_dat'] .= $this->getFeedXmlForTags('category', $eventData['properties']['freetag_tags'] ?? []); return true; case 'frontend_display:rss-1.0:per_entry': case 'frontend_display:rss-0.91:per_entry': case 'frontend_display:atom-0.3:per_entry': case 'frontend_display:atom-1.0:per_entry': $eventData['display_dat'] .= $this->getFeedXmlForTags('dc:subject', $eventData['properties']['freetag_tags']); return true; case 'external_plugin': $uri_parts = explode('?', str_replace(array('&', '%FF'), array('&', '.'), $eventData)); $taglist = serendipity_db_bool($this->get_config('taglist', false)); $param = $taglist ? explode('/', str_replace('/taglist','',$uri_parts[0])) : explode('/', $uri_parts[0]); $plugincode = array_shift($param); $tagged_as_list = false; // By option or manually added blogdomain.com/plugin/taglist/Serendipity/Blog/Plums - see below if ($plugincode == "taglist") $plugincode = "tags"; if (($plugincode == "tag") || ($plugincode == "tags") || ($plugincode == "freetag")) { // Manually added (last) parameter 'taglist" to view tags by list for certain taglinks eg. blogdomain.com/plugin/tag/Serendipity/Blog/Plums/taglist - both need a modified entries.tpl if ($taglist && in_array('taglist', $serendipity['uriArguments'])) { $param = array_map('urldecode', $param); $param = array_map('urldecode', $param); // for doubled encoded tag umlauts via searchengines backlinks $param = is_array($param) ? array_map('strip_tags', $param) : strip_tags($param); $param = array_filter($param); // empty removed XSS by strip_tags if (!is_object($serendipity['smarty'])) { serendipity_smarty_init(); // to avoid member function assign() on a non-object error, start Smarty templating } if (false === serendipity_db_bool($this->get_config('show_tagcloud', true))) { // Since this is extra stuff, we need to regular assign the subtitle header and not use $serendipity['head_subtitle'] ! if (count($param) > 1) { if (function_exists('serendipity_specialchars')) { $serendipity['smarty']->assign('head_subtitle', sprintf(PLUGIN_EVENT_FREETAG_USING, implode(' + ', array_map('serendipity_specialchars', $param)))); } else { $serendipity['smarty']->assign('head_subtitle', sprintf(PLUGIN_EVENT_FREETAG_USING, implode(' + ', array_map('htmlspecialchars', $param)))); } } else { $serendipity['smarty']->assign('head_subtitle', sprintf(PLUGIN_EVENT_FREETAG_USING, (function_exists('serendipity_specialchars') ? serendipity_specialchars($param[0]) : htmlspecialchars($param[0], ENT_COMPAT, LANG_CHARSET)))); } } $serendipity['smarty']->assign('taglist', true); foreach($serendipity['uriArguments'] AS $uak => $uav) { if ($uav == 'taglist') unset($serendipity['uriArguments'][$uak]); } $tagged_as_list = true; } /* Attempt to locate hidden variables within the URI */ foreach ($serendipity['uriArguments'] as $k => $v) { if ($v[0] == 'P') { /* Page */ $page = substr($v, 1); if (is_numeric($page)) { $serendipity['GET']['page'] = $page; unset($serendipity['uriArguments'][$k]); if ($param[count($param)-1] == "P{$page}.html") { array_pop($param); // knock it off of the param array as well } } } } if (count($param) == 0 || empty($param[0])) { $serendipity['head_subtitle'] = PLUGIN_EVENT_FREETAG_ALLTAGS; $this->displayTag = true; $param = null; } else if (count($param) == 1) { $param = urldecode($param[0]); $param = urldecode($param); // for doubled encoded tag umlauts via searchengines backlinks $param = strip_tags($param); $serendipity['head_subtitle'] = sprintf(PLUGIN_EVENT_FREETAG_USING, (function_exists('serendipity_specialchars') ? serendipity_specialchars($param) : htmlspecialchars($param, ENT_COMPAT, LANG_CHARSET))); $emit_404 = true; } else { if (!$tagged_as_list) { $param = array_map('urldecode', $param); $param = array_map('urldecode', $param); // for doubled encoded tag umlauts via searchengines backlinks in sprintf } $param = array_map('strip_tags', $param); $param = array_filter($param); // empty removed XSS by strip_tags if (function_exists('serendipity_specialchars')) { $serendipity['head_subtitle'] = sprintf(PLUGIN_EVENT_FREETAG_USING, implode(' + ', array_map('serendipity_specialchars', $param))); } else { $serendipity['head_subtitle'] = sprintf(PLUGIN_EVENT_FREETAG_USING, implode(' + ', array_map('htmlspecialchars', $param))); } $emit_404 = true; } // for XSS secureness, while using doubled decode $param = is_array($param) ? array_map('strip_tags', $param) : strip_tags($param); if (is_array($param)) { array_filter($param); // empty removed XSS by strip_tags } if (function_exists('serendipity_specialchars')) { $param = is_array($param) ? array_map('serendipity_specialchars', $param) : serendipity_specialchars($param); } else { $param = is_array($param) ? array_map('htmlspecialchars', $param) : htmlspecialchars($param, ENT_COMPAT, LANG_CHARSET); } $this->tags['show'] = $param; $serendipity['plugin_vars']['tag'] = $param; if (is_array($param)) { @define('PLUGIN_VARS_TAG', implode(',', $param)); } else { @define('PLUGIN_VARS_TAG', $param); } $serendipity['GET']['subpage'] = $eventData; unset($serendipity['GET']['category']); // No restriction should be enforced here. include_once(S9Y_INCLUDE_PATH . 'include/genpage.inc.php'); if ($emit_404 && $this->TaggedEntries !== null && $this->TaggedEntries < 1) { @header('HTTP/1.0 404 Not found'); @header('Status: 404 Not found'); if (serendipity_db_bool($this->get_config('send_http_header', true))) { @header('X-FreeTag: not found'); } } else { if (serendipity_db_bool($this->get_config('send_http_header', true))) { @header('X-FreeTag: ' . $this->TaggedEntries); } } $raw_data = ob_get_contents(); ob_end_clean(); $serendipity['smarty']->assign('raw_data', $raw_data); serendipity_gzCompression(); $serendipity['smarty']->display(serendipity_getTemplateFile($serendipity['smarty_file'], 'serendipityPath')); @define('NO_EXIT', true); } break; case 'backend_sidebar_entries': if ($serendipity['version'][0] < 2) { ?>
  • eventData = $eventData; $this->displayManageTags($event, $bag, $eventData, $addData); return true; break; case 'backend_publish': case 'backend_save': if (function_exists('mb_internal_encoding')) { mb_internal_encoding(LANG_CHARSET); } if (!isset($eventData['id'])) { return true; } $to_lower = serendipity_db_bool($this->get_config('lowercase_tags')); $keylist = serendipity_db_query("SELECT tag, keywords FROM {$serendipity['dbPrefix']}tagkeywords", false, 'assoc'); $automatted = array(array()); if (is_array($keylist)) { foreach($keylist AS $key) { $keywords = explode(',', $key['keywords']); foreach($keywords AS $keyword) { $automatted[trim($keyword)][$key['tag']] = true; } } } // When this variable is not set, the entry might be saved i.e. by recreating cache or automatted trackback. // Do not loose such tags. :) if (!isset($serendipity['POST']['properties']['freetag_tagList'])) { $serendipity['POST']['properties']['freetag_tagList'] = implode(',', $this->getTagsForEntry($eventData['id'])); } $tags = $this->makeTagsFromTagList($serendipity['POST']['properties']['freetag_tagList']); if (serendipity_db_bool($this->get_config('keyword2tag'))) { $searchtext = strip_tags($eventData['body'] . $eventData['extended']); foreach($automatted AS $keyword => $ktags) { $keyword = trim($keyword); if (empty($keyword)) continue; if (!is_array($ktags) || count($ktags) < 1) continue; $regex = sprintf("/((\s+|[\(\[-]+)%s([-\/,\.\?!'\";\)\]]*+|[\/-]+))/i", $keyword); if (preg_match($regex, $searchtext) > 0) { foreach($ktags AS $tag => $is_assigned) { if (!is_array($tags) || (!in_array(strtolower($tag), $tags) && !in_array($tag, $tags))) { if ($to_lower) { if (function_exists("mb_strtolower")) { $tag = mb_strtolower($tag); } else { $tag = strtolower($tag); } } $tags[] = $tag; printf(PLUGIN_EVENT_FREETAG_KEYWORDS_ADD, (function_exists('serendipity_specialchars') ? serendipity_specialchars($keyword) : htmlspecialchars($keyword, ENT_COMPAT, LANG_CHARSET)), (function_exists('serendipity_specialchars') ? serendipity_specialchars($tag) : htmlspecialchars($tag, ENT_COMPAT, LANG_CHARSET))); } } } } } if (empty($tags)) { $tags = array(); } if (serendipity_db_bool($this->get_config('cat2tag'))) { if (is_array($cats = serendipity_fetchCategories())) { $cats = serendipity_walkRecursive($cats, 'categoryid', 'parentid', VIEWMODE_THREADED); foreach ($cats as $cat) { if ($to_lower) { if (function_exists("mb_strtolower")) { $cat['category_name'] = mb_strtolower($cat['category_name']); } else { $cat['category_name'] = strtolower($cat['category_name']); } } $names = explode(',', $cat['category_name']); foreach($names AS $name) { $name = trim($name); if (is_array($eventData['categories']) && in_array($cat['categoryid'], $eventData['categories']) && !in_array($name, $tags)) { $tags[] = $name; } } } } } $serendipity['POST']['properties']['freetag_tagList'] = implode(',', $tags); $this->deleteTagsForEntry($eventData['id']); $this->addTagsToEntry($eventData['id'], $tags); if ($serendipity['POST']['properties']['freetag_kill'] ?? false) { $this->deleteTagsForEntry($eventData['id']); } return true; break; case 'css_backend': if ($serendipity['version'][0] > 1) { ?> .freetagMenu li { display: block; margin: 0 0 .5em; } .freetags_manage { border: 1px solid #aaa; border-bottom: 0 none; width: 100%; } .freetags_manage thead tr { background-color: #eee; } .freetags_manage tr { border-bottom: 1px solid #aaa; } .freetags_manage th, .freetags_manage td { padding: .125em .25em; } .freetags_list li { margin: 0 0 .25em; } @media only screen and (min-width: 768px) { .freetagMenu li { display: inline-block; margin: 0 .25em .5em 0; } } get_config('admin_ftayt')) { echo ' function enableAutocomplete() { if (typeof(tags) != "undefined") { $("#properties_freetag_tagList").autocomplete(tags, { minChars: 0, multiple: true, scrollHeight: 200, matchContains: "word", autoFill: false }); } }; addLoadEvent(enableAutocomplete); '; } break; case 'backend_display': if (function_exists('mb_internal_encoding')) { mb_internal_encoding(LANG_CHARSET); } if (!empty($serendipity['POST']['properties']['freetag_tagList'])) { $tagList = $serendipity['POST']['properties']['freetag_tagList']; } else if (isset($eventData['id'])) { $tagList = implode(',', $this->getTagsForEntry($eventData['id'])); } else { $tagList = ''; } if (serendipity_db_bool($this->get_config('lowercase_tags', true))) { if (function_exists("mb_strtolower")) { $tagList = mb_strtolower($tagList); } else { $tagList = strtolower($tagList); } } $freetags = $this->makeTagsFromTagList($tagList); if (!empty($freetags)) { $tagList = implode(',', $freetags); } $taglist = (array)$this->getAllTags(); $wicktags = array(); if ($this->get_config('admin_ftayt')) { foreach ($taglist as $k => $v) { $wicktags[] = '\'' . addslashes($k) . '\''; } // jQuery Migrate is used due to $.browser of autocomplete plugin not being available in jquery 1.9+ echo ' ' . ($serendipity['version'][0] < 2 ? '' : '') . ' '; } if ($this->get_config('admin_show_taglist')) { ?>


    get_config('admin_show_taglist')) { ?>
    get_config('admin_show_taglist')) { ?>
    get_config('admin_show_taglist')) { $lastletter = ''; foreach ($taglist as $tag => $count) { if (function_exists('mb_strtoupper')) { $upc = mb_strtoupper(mb_substr($tag, 0, 1, LANG_CHARSET), LANG_CHARSET); } else { $upc = strtoupper(substr($tag, 0, 1)); } if ($upc != $lastletter) { if ($serendipity['version'][0] < 2) { echo " |" . $upc . ': '; } } if ($serendipity['version'][0] < 2) { echo "$tag, "; } else { echo "$tag "; } $lastletter = $upc; } echo "
    "; } ?>
    importEntryTagsIntoProperties($eventData, $addData); return true; break; case 'frontend_fetchentries': case 'frontend_fetchentry': if (!empty($this->tags['show'])) { if (is_array($this->tags['show'])) { $showtag = array_map('serendipity_db_escape_string', $this->tags['show']); } else { $showtag = serendipity_db_escape_string($this->tags['show']); } } else if (!empty($serendipity['GET']['tag'])) { $showtag = serendipity_db_escape_string(urldecode($serendipity['GET']['tag'])); } if (is_array($showtag ?? null)) { $arr_showtag = $showtag; } else { $arr_showtag = explode(';', $showtag ?? ''); } $multimode = 'and'; if (count($arr_showtag) > 1) { $showtag = $arr_showtag; $multimode = 'or'; } if (!empty($show_tag) && is_string($show_tag) && serendipity_db_bool($this->get_config('lowercase_tags', true))) { if (function_exists("mb_strtolower")) { if (function_exists('mb_internal_encoding')) { mb_internal_encoding(LANG_CHARSET); } $showtag = mb_strtolower($showtag); } else { $showtag = strtolower($showtag); } } $coll_target = $this->get_config('collation', ''); if (empty($coll_target) && stristr($serendipity['dbType'], 'mysql') ) { $cd = serendipity_db_query("SHOW FULL COLUMNS FROM {$serendipity['dbPrefix']}entrytags LIKE 'tag'"); if (!empty($cd[0]['Collation'])) { $coll_target = $cd[0]['Collation']; $this->set_config('collation', $coll_target); } } if (!empty($showtag)) { if (LANG_CHARSET == 'UTF-8' && stristr($serendipity['dbType'], 'mysql') && !stristr($coll_target, 'utf8')) { $collate = "COLLATE utf8_general_ci"; $collateP = '_utf8 '; } else { $collate = $collateP = ""; } $cond = $join = ''; if (is_string($showtag)) { $join = "INNER JOIN {$serendipity['dbPrefix']}entrytags AS entrytags ON (e.id = entrytags.entryid) "; $cond = "entrytags.tag = $collateP '$showtag' $collate"; } else if (is_array($showtag)) { $_taglist = array(); $cond = '(1=2 '; foreach($showtag AS $_showtag) { $_taglist[] = serendipity_db_escape_string($_showtag); $cond .= " OR entrytags.tag = $collateP '" . serendipity_db_escape_string($_showtag) . "' $collate "; } $cond .= ' ) '; $total = count($showtag); $join = "INNER JOIN {$serendipity['dbPrefix']}entrytags AS entrytags ". "ON e.id = entrytags.entryid "; if ($multimode == 'and') { $eventData['having'] = " HAVING count(entrytags.tag) = $total"; } } if (empty($eventData['and'])) { $eventData['and'] = " WHERE $cond "; } else { $eventData['and'] .= " AND $cond "; } if (empty($eventData['joins'])) { $eventData['joins'] = $join; } else { $eventData['joins'] .= $join; } $this->displayTag = $showtag; $serendipity['plugin_vars']['displayTag'] = $showtag; if (! defined('PLUGIN_VARS_DISPLAYTAG')) { @define('PLUGIN_VARS_DISPLAYTAG', $showtag); } } return true; break; case 'frontend_rss': if (!empty($this->displayTag)) { $eventData['title'] .= serendipity_utf8_encode((function_exists('serendipity_specialchars') ? serendipity_specialchars(' (' . sprintf(PLUGIN_EVENT_FREETAG_USING, $this->displayTag) . ')') : htmlspecialchars(' (' . sprintf(PLUGIN_EVENT_FREETAG_USING, $this->displayTag) . ')', ENT_COMPAT, LANG_CHARSET))); } return true; break; case 'entries_header': if (isset($eventData['plugin_vars']['tag']) && serendipity_db_bool($this->get_config('show_tagcloud'))) { $this->displayTagCloud($eventData['plugin_vars']['tag']); } return true; break; case 'css': if (strpos($eventData, '.serendipity_freeTag')) { // class exists in CSS, so a user has customized it and we don't need default return true; } $this->addToCSS($eventData); return true; break; case 'entry_display': // Don't display entries if we are getting a full tag list if (is_array($eventData)) { $this->TaggedEntries = count($eventData); if (serendipity_db_bool($this->get_config('send_http_header', true))) { @header('X-FreeTag-Count: Array'); } } else { if (serendipity_db_bool($this->get_config('send_http_header', true))) { @header('X-FreeTag-Count: Empty'); } $this->TaggedEntries = 0; } if ($this->displayTag === true) { $eventData['clean_page'] = true; return true; } $this->displayEntry($eventData, $addData); return true; break; case 'xmlrpc_updertEntry': if (isset($eventData['id']) && isset($eventData['mt_keywords'])) { //XMLRPC call $tags = $this->makeTagsFromTagList($eventData['mt_keywords']); if (!empty($tags)) { $this->deleteTagsForEntry($eventData['id']); $this->addTagsToEntry($eventData['id'], $tags); } } return true; break; case 'xmlrpc_fetchEntry': $eventData['mt_keywords']=implode(',', $this->getTagsForEntry($eventData['id'])); return true; break; case 'xmlrpc_deleteEntry': if (isset($eventData["id"])) { $this->deleteTagsForEntry($eventData["id"]); } return true; break; default: return false; break; } } else { return false; } } function displayEntry(&$eventData, $addData) { global $serendipity; $show_related = serendipity_db_bool($this->get_config('show_related', true)); if (is_array($eventData)) { $elements = count($eventData); } else { return; } // If not using extended-smarty, we want related entries only when // showing only one entry. It is better to ask Smarty here than doing // this manually for edge cases like overview pages if ($serendipity['version'][0] > 1) { $manyEntries = ! $serendipity['smarty']->getTemplateVars('is_single_entry'); } else { $manyEntries = ! $serendipity['smarty']->get_template_vars('is_single_entry'); } for ($entry = 0; $entry < $elements; $entry++) { $tags = $this->getTagsForEntry($eventData[$entry]['id']); //when in preview, maybe there are no tags stored yet if ($addData['preview'] && empty($tags)) { $tags = explode(',', $serendipity['POST']['properties']['freetag_tagList']); } $eventData = $this->addTags($entry, $tags, $eventData); if ($show_related) { $relatedEntries = $this->getRelatedEntries($tags, $eventData[$entry]['id']); $eventData = $this->addRelatedEntries($entry, $manyEntries, $relatedEntries, $eventData); } } } /** * Add related entries to eventData[$entry] * * $entry: number of entry in $eventData * for use in displayEntry */ function addRelatedEntries($entry, $manyEntries, $relatedEntries, $eventData) { if (is_array($relatedEntries)) { if ($this->get_config('extended_smarty', false)) { $eventData[$entry]['freetag']['extended'] = true; $eventData[$entry]['freetag']['related'] = $this->getRelatedEntriesHtml($relatedEntries, true); } else if (! $manyEntries){ $field = $this->getField($eventData, $entry); //work with getFieldReference to prevent caching-issues $entryText =& $this->getFieldReference($field, $eventData[$entry]); $entryText .= $this->getRelatedEntriesHtml($relatedEntries); } } return $eventData; } /** * $entry: number of entry in $eventData * for use in displayEntry */ function addTags($entry, $tags, $eventData) { if (!is_array($eventData)) $eventData = array(); if ($this->get_config('extended_smarty', false)) { $eventData[$entry]['freetag']['extended'] = true; $eventData[$entry]['freetag']['tags']['description'] = str_replace('%s', '', PLUGIN_EVENT_FREETAG_LIST); $eventData[$entry]['freetag']['tags']['tags'] = $this->getTagHtml($tags, true); } else { if (!empty($tags)) { $field = $this->getField($eventData, $entry); $msg = '
    ' . PLUGIN_EVENT_FREETAG_LIST . '
    '; //in preview, $eventData maybe don't contain the field - till now if (!isset($eventData[$entry][$field])) { $eventData[$entry][$field] = ""; } $entryText =& $this->getFieldReference($field, $eventData[$entry]); $entryText .= sprintf($msg, $this->getTagHtml($tags)); } } return $eventData; } function getField($eventData, $entry) { $embed_footer = $this->get_config('embed_footer'); if ($embed_footer === 'yes' || ($embed_footer !== 'no' && serendipity_db_bool($embed_footer))) { $field = 'add_footer'; } else if ($embed_footer === 'smarty') { $field = 'freetag'; } else { //The option is set to add to the entry, but where? if (strlen($eventData[$entry]['extended']) > 0) { $field = 'extended'; } else { $field = 'body'; } } return $field; } /** * Returns a list of all tags * This performs a memoization operation, so that if we happen to be * getting all tags more then one time per request, we only perform * the SQL query once */ // static static function makeTagsFromTaglist($tagList) { $tags = []; $freetags = explode(',', $tagList); foreach($freetags AS $tag) { $tag = trim($tag); if (!empty($tag)) { $tags[] = $tag; } } return $tags; } static function getAllTags() { global $serendipity; static $memo = false; if (is_array($memo)) { return $memo; } $q = "SELECT tag, count(tag) as total FROM {$serendipity['dbPrefix']}entrytags GROUP BY tag ORDER BY tag"; $rows = serendipity_db_query($q); if (!is_array($rows)) { return array(); } $memo = array(); foreach((array)$rows as $r) { $memo[$r['tag']] = $r['total']; } serendipity_plugin_api::hook_event('sort', $memo); return $memo; } function displayTagCloud($tag) { global $serendipity; $tags = $this->getTagCloudTags($tag); $serendipity['smarty']->assign('freetag_tagTitle', (function_exists('serendipity_specialchars') ? serendipity_specialchars(is_array($this->displayTag) ? implode(' + ',$this->displayTag) : $this->displayTag) : htmlspecialchars(is_array($this->displayTag) ? implode(' + ',$this->displayTag) : $this->displayTag, ENT_COMPAT, LANG_CHARSET))); if (!empty($tags)) { $serendipity['smarty']->assign('freetag_hasTags', true); $min = $this->get_config('min_percent', 100); $max = $this->get_config('max_percent', 300); ob_start(); serendipity_event_freetag::displayTags($tags, false, false, true, $max, $min, serendipity_db_bool($this->get_config('use_flash')), serendipity_db_bool($this->get_config('flash_bg_trans', true)), $this->get_config('flash_tag_color', 'ff6600'), $this->get_config('flash_bg_color', 'ffffff'), $this->get_config('flash_width', 600), $this->get_config('flash_speed', 100), $this->get_config('taglink'), $this->get_config('template'), $this->get_config('xml_image','img/xml.gif')); $tagout = ob_get_contents(); ob_end_clean(); $serendipity['smarty']->assign('freetag_displayTags', $tagout); } else { $serendipity['smarty']->assign('freetag_hasTags', false); } $content = $this->parseTemplate('plugin_freetag.tpl'); echo $content; } # # descend: if true, get the related tags of the related tags of given tag # function getTagCloudTags($tag, $descend = true) { $rows = serendipity_db_query($this->getTagCloudQuery('', $tag)); $tags = []; if (is_array($rows)) { foreach((array)$rows as $r) { $tags[$r['tag']] = $r['total']; #get also tags which are related only by other tags if($descend) { $descended_tags = $this->getTagCloudTags($r['tag'], false); if (is_array($descended_tags)) { foreach($descended_tags AS $dtag => $value) { $descended_tags[$dtag] = $value / 2; } $tags = $tags + $descended_tags; } } } } unset($tags[$tag]); return $tags; } function getTagCloudQuery($sort = '', $tag = false) { global $serendipity; if ($tag === true) { $q = "SELECT tag, count(tag) as total FROM {$serendipity['dbPrefix']}entrytags GROUP BY tag ORDER BY tag"; } else { if (is_string($tag)) { $cond = "main.tag = '" . serendipity_db_escape_string($tag) . "'"; $ncond = "neg.tag != '" . serendipity_db_escape_string($tag) . "'"; $join = "LEFT JOIN {$serendipity['dbPrefix']}entrytags AS neg ". "ON main.entryid = neg.entryid "; $totalModifier = ''; } else if (is_array($tag)) { $join = "LEFT JOIN {$serendipity['dbPrefix']}entrytags AS neg ". "ON main.entryid = neg.entryid "; $ccond = ''; $ncond = ''; $first = true; $total = count($tag); $totalModifier = " - $total"; for ($i = 0; $i < $total; $i++) { if (!$first) { $ncond .= " AND "; $cond .= " AND "; } else { $first = false; } $join .= "LEFT JOIN {$serendipity['dbPrefix']}entrytags AS sub{$i} ". "ON main.entryid = sub{$i}.entryid "; $cond .= "sub{$i}.tag = '" . serendipity_db_escape_string($tag[$i]) . "' "; $ncond .= "neg.tag != '" . serendipity_db_escape_string($tag[$i]) . "' "; } } else { return; } $q = "SELECT neg.tag AS tag, count(neg.tag) {$totalModifier} AS total FROM {$serendipity['dbPrefix']}entrytags AS main {$join} WHERE ($cond) AND ($ncond) GROUP BY neg.tag"; } if (serendipity_db_bool($this->get_config('use_flash'))) { $mt = $this->get_config('max_tags', 45); } else { $mt = $this->get_config('max_tags', 0); } if ($mt > 0 && $sort == '') { $q = $q . " LIMIT " . $mt; } return $q; } function displayMetaKeywords($id = null, $tag = false) { global $serendipity; $id = (int)$id; $max_keywords = (int)$this->get_config('meta_keywords', 0); if ($max_keywords < 1) { return; } if ($tag !== false && $tag !== true) { //show related tags $query = $this->getTagCloudQuery(' ORDER BY total DESC LIMIT ' . $max_keywords, $tag); } else if ($id == null) { // show all tags // select most used tags in descending order $query = "SELECT tag, count(tag) AS total FROM {$serendipity['dbPrefix']}entrytags GROUP BY tag ORDER BY total DESC LIMIT " . $max_keywords; } else { // show tags for entry // select tags from entry $id ordered by most usage descending $query = "SELECT one.tag, two.entryid, count(two.tag) AS total FROM {$serendipity['dbPrefix']}entrytags AS one JOIN {$serendipity['dbPrefix']}entrytags AS two ON two.entryid = " . $id . " AND one.tag = two.tag GROUP BY one.tag, two.entryid ORDER BY total DESC LIMIT " . $max_keywords; } $rows = serendipity_db_query($query); if (!is_array($rows)) { return; } echo "tags['show'])) { if (is_array($this->tags['show'])) { $not_first = false; foreach($this->tags['show'] AS $r) { $not_first ? print(', ') : $not_first = true; echo $r; } } else { echo $this->tags['show']; $not_first = true; } } foreach($rows AS $r) { if (empty($r['tag'])) { continue; } $not_first ? print(', ') : $not_first = true; echo (function_exists('serendipity_specialchars') ? serendipity_specialchars($r['tag']) : htmlspecialchars($r['tag'], ENT_COMPAT, LANG_CHARSET)); } echo "\" />"; } function getRelatedTags($tag) { global $serendipity; $q = "SELECT sub.tag AS tag, count(sub.tag) AS total FROM {$serendipity['dbPrefix']}entrytags AS main LEFT JOIN {$serendipity['dbPrefix']}entrytags AS sub ON main.entryid = sub.entryid WHERE main.tag = '$tag' AND sub.tag != '$tag' GROUP BY sub.tag ORDER BY sub.tag"; $rows = serendipity_db_query($q); if (!is_array($rows)) { if ($rows !== true && $rows !== 1 && $rows !== 'true') { echo $rows; } return array(); } foreach($rows as $r) { $tags[$r['tag']] = $r['total']; } return $tags; } function getLeafTags($leafWeight=1) { global $serendipity; $q = "SELECT tag, count(tag) as total FROM {$serendipity['dbPrefix']}entrytags GROUP BY tag HAVING count(tag) <= $leafWeight ORDER BY tag"; $rows = serendipity_db_query($q); if (!is_array($rows)) { echo $rows; } $tags = array(); foreach((array)$rows as $r) { if (is_array($r)) { $tags[$r['tag']] = $r['total']; } } return $tags; } static function getTagsForEntries($entries) { global $serendipity; if (!is_array($entries) || count($entries) < 1 || implode(',', $entries) == '') { return false; } $q = "SELECT entryid, tag from {$serendipity['dbPrefix']}entrytags WHERE entryid IN (".implode(',', $entries).") order by entryid, tag"; $result = serendipity_db_query($q); if (!is_array($result)) { return false; } $return = array(); foreach($result as $row) { if (isset($row['entryid'])) { $return[$row['entryid']][] = $row['tag']; } } return $return; } function getTagsForEntry($entryId) { $array = $this->getTagsForEntries(array($entryId)); return (is_array($array) ? array_pop($array) : array()); } function deleteTagsForEntry($entryId) { global $serendipity; $q = "DELETE FROM {$serendipity['dbPrefix']}entrytags WHERE entryid = ".(int)$entryId; serendipity_db_query($q); } // Static static function addTagsToEntry($entryId, $tags) { global $serendipity; if (!is_array($tags)) { return false; } foreach($tags as $tag) { $q = "INSERT INTO {$serendipity['dbPrefix']}entrytags (entryid, tag) VALUES (".(int)$entryId.", '".serendipity_db_escape_string($tag)."')"; serendipity_db_query($q); } } // This may not be the right way to do this... function importEntryTagsIntoProperties(&$eventData, $addData) { // we do a dual loop here, which is probably the worst thing to do. // A better thing might be some kind of array merge action, but I am not // entirely sure how do do that with the arrays we are given. // // RefactorMe Later. // Loop one in getTagsForEntries $tagGroups = $this->getTagsForEntries(array_keys($addData)); // Loop 2 if (is_array($tagGroups)) { foreach($tagGroups as $entryId => $tagList) { $eventData[$addData[$entryId]]['properties']['freetag_tags'] = $tagList; $eventData[$addData[$entryId]]['properties']['freetag_tagList'] = implode(",", $tagList); } } } function getFeedXmlForTags($element, $tagList) { $out = ''; if (!is_array($tagList)) { return $out; } foreach($tagList as $tag) { $out .= serendipity_utf8_encode("<$element>".(function_exists('serendipity_specialchars') ? serendipity_specialchars($tag) : htmlspecialchars($tag, ENT_COMPAT, LANG_CHARSET)) ."\n"); } return $out; } function displayManageTags($event, &$bag, &$eventData, $addData) { global $serendipity; if ($this->get_config('dbversion', 1) != 2) { $this->install(); $this->set_config('dbversion', 2); } if ($serendipity['version'][0] < 2) { ?>

      eventData['GET']['tagaction']) && !empty($this->eventData['GET']['tagaction'])) { $this->displayTagAction(); } if (isset($this->eventData['GET']['tagview'])) { switch ($this->eventData['GET']['tagview']) { case "entryuntagged": $this->displayUntaggedEntries(); break; case "entryleaf": $this->displayLeafTaggedEntries(); break; case "all": $tags = (array)$this->getAllTags(); $this->displayEditTags($tags); break; case "leaf": $tags = $this->getLeafTags(); $this->displayEditTags($tags); break; case 'keywords': $tags = (array)$this->getAllTags(); $this->displayKeywordAssignment($tags); break; case 'tagupdate': $per_fetch = 25; $page = (isset($serendipity['GET']['page']) ? $serendipity['GET']['page'] : 1); $from = ($page - 1) * $per_fetch; $to = ($page) * $per_fetch; if ($serendipity['version'][0] > 1) { echo '

      '; } printf(PLUGIN_EVENT_FREETAG_REBUILD_FETCHNO, $from, $to); $entries = serendipity_fetchEntries( null, true, $per_fetch, false, false, 'timestamp DESC', '', true ); $total = serendipity_getTotalEntries(); if ($serendipity['version'][0] < 2) { printf(PLUGIN_EVENT_FREETAG_REBUILD_TOTAL . '
      ', $total); } else { printf(PLUGIN_EVENT_FREETAG_REBUILD_TOTAL, $total); echo '

      '; } if (is_array($entries)) { if ($serendipity['version'][0] > 1) { echo '
        '; } foreach ($entries AS $entry) { unset($entry['orderkey']); unset($entry['loginname']); unset($entry['email']); if ($serendipity['version'][0] < 2) { printf('%d - "%s"
        ', $entry['id'], (function_exists('serendipity_specialchars') ? serendipity_specialchars($entry['title']) : htmlspecialchars($entry['title'], ENT_COMPAT, LANG_CHARSET))); } else { printf('
      • %d - "%s"', $entry['id'], (function_exists('serendipity_specialchars') ? serendipity_specialchars($entry['title']) : htmlspecialchars($entry['title'], ENT_COMPAT, LANG_CHARSET))); } $serendipity['POST']['properties']['fake'] = 'fake'; $current_cat = $entry['categories']; $entry['categories'] = array(); foreach ($current_cat AS $categoryidx => $category_data) { $entry['categories'][$category_data['categoryid']] = $category_data['categoryid']; } $up = serendipity_updertEntry($entry); if (is_string($up)) { echo "
        $up
        \n"; } if ($serendipity['version'][0] < 2) { echo DONE . "
        \n"; } else { echo ' ... ' . DONE . "
      • \n"; } } if ($serendipity['version'][0] > 1) { echo '
      '; } } if ($serendipity['version'][0] < 2) { echo '
      '; } if ($to < $total) { ?> ' . DONE . '
    '; } else { echo '' . DONE . ''; } } break; case 'cat2tag': $e = serendipity_db_query( "SELECT e.id, e.title, c.category_name, et.tag FROM {$serendipity['dbPrefix']}entries AS e LEFT OUTER JOIN {$serendipity['dbPrefix']}entrycat AS ec ON e.id = ec.entryid LEFT OUTER JOIN {$serendipity['dbPrefix']}category AS c ON ec.categoryid = c.categoryid LEFT OUTER JOIN {$serendipity['dbPrefix']}entrytags AS et ON e.id = et.entryid", false, 'assoc' ); // Get all categories and tags of all entries $entries = array(); foreach ($e AS $row) { $entries[$row['id']]['title'] = $row['title']; $entries[$row['id']]['categories'][$row['category_name']] = $row['category_name']; $entries[$row['id']]['tags'][$row['tag']] = $row['tag']; } // Cycle all entries if ($serendipity['version'][0] > 1) { echo ''; } if ($serendipity['version'][0] < 2) { echo PLUGIN_EVENT_FREETAG_GLOBALCAT2TAG . '
    '; } else { echo '' . PLUGIN_EVENT_FREETAG_GLOBALCAT2TAG . ''; } break; case 'cleanupmappings': $this->cleanupTagAssignments(); break; default: if (!empty($this->eventData['GET']['tagview'])) { echo "Can't execute tagview"; } break; } } return true; } function displayUntaggedEntries() { global $serendipity; $q = "SELECT e.id as id, e.title as title FROM ${serendipity['dbPrefix']}entries AS e LEFT OUTER JOIN ${serendipity['dbPrefix']}entrytags AS t ON e.id = t.entryid WHERE entryid IS NULL GROUP BY e.id, e.title"; $this->displayEditEntries($q); } function displayLeafTaggedEntries() { global $serendipity; $q = "SELECT e.id as id, e.title as title, count(t.tag) as total FROM ${serendipity['dbPrefix']}entries AS e LEFT JOIN ${serendipity['dbPrefix']}entrytags AS t ON e.id = t.entryid GROUP BY e.id, e.title HAVING total = 1"; $this->displayEditEntries($q); } function displayEditEntries($q) { global $serendipity; $r = serendipity_db_query($q); if ($r === true) { if ($serendipity['version'][0] < 2) { echo PLUGIN_EVENT_FREETAG_MANAGE_UNTAGGED_NONE; } else { echo ' ' . PLUGIN_EVENT_FREETAG_MANAGE_UNTAGGED_NONE . ''; } } else if (!is_array($r)) { echo $r; } else { if ($serendipity['version'][0] > 1) { echo ''; } } } function displayKeywordAssignment($taglist) { global $serendipity; if ($serendipity['POST']['keywordsubmit']) { serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}tagkeywords WHERE tag = '" . serendipity_db_escape_string(urldecode($serendipity['POST']['tag'])) . "'"); serendipity_db_query("INSERT INTO {$serendipity['dbPrefix']}tagkeywords (tag, keywords) VALUES ('" . serendipity_db_escape_string(urldecode($serendipity['POST']['tag'])) . "', '" . serendipity_db_escape_string($serendipity['POST']['keywords']) . "')"); } $keys = array(); $keylist = serendipity_db_query("SELECT tag, keywords FROM {$serendipity['dbPrefix']}tagkeywords ORDER BY tag"); if (is_array($keylist)) { foreach($keylist AS $key) { $keys[$key['tag']] = $key['keywords']; } } $url = FREETAG_MANAGE_URL . "&serendipity[tagview]=".(function_exists('serendipity_specialchars') ? serendipity_specialchars($this->eventData['GET']['tagview']) : htmlspecialchars($this->eventData['GET']['tagview'], ENT_COMPAT, LANG_CHARSET)); if ($serendipity['version'][0] < 2) { echo '
    ' . PLUGIN_EVENT_FREETAG_KEYWORDS_DESC . '

    '; } else { echo '' . PLUGIN_EVENT_FREETAG_KEYWORDS_DESC . ''; } ?>
    $weight) { ?>
    eventData['GET']['tagview']) : htmlspecialchars($this->eventData['GET']['tagview'], ENT_COMPAT, LANG_CHARSET)); ?> $weight) { ?>
    eventData['GET']['tag']); $action = urldecode($this->eventData['GET']['tagaction']); if (!in_array($this->eventData['GET']['tagaction'], $validActions)) exit ("DON'T HACK!"); if ($this->eventData['GET']['commit'] == 'true') { $method = 'get'.$this->eventData['GET']['tagaction'].'TagQuery'; $q = $this->$method($tag, $this->eventData); echo $this->eventData['GET']['tagaction'] . " Completed"; } else { $method = 'display'.$this->eventData['GET']['tagaction']."Tag"; $this->$method($tag, $this->eventData); } } function getManageUrlAsHidden(&$eventData) { return ' '; } function displayRenameTag($tag, &$eventData) { ?>
    getManageUrlAsHidden($this->eventData) ?> =>
    eventData['GET']['tagview']) : htmlspecialchars($this->eventData['GET']['tagview'], ENT_COMPAT, LANG_CHARSET)); $yes = FREETAG_MANAGE_URL . "&serendipity[tagview]=".(function_exists('serendipity_specialchars') ? serendipity_specialchars($this->eventData['GET']['tagview']) : htmlspecialchars($this->eventData['GET']['tagview'], ENT_COMPAT, LANG_CHARSET)). "&serendipity[tagaction]=delete". "&serendipity[tag]=".urlencode($tag)."&serendipity[commit]=true"; ?>

       

    getManageUrlAsHidden($this->eventData) ?>


    foobarbaz => foo,bar,baz

    =>
    makeTagsFromTaglist(urldecode($this->eventData['GET']['newtags'])); $tag = serendipity_db_escape_string($tag); $q = "SELECT entryid from ${serendipity['dbPrefix']}entrytags where tag = '$tag'"; $entries = serendipity_db_query($q); if (!is_array($entries)) { echo $entries; return false; } $q = "DELETE FROM ${serendipity['dbPrefix']}entrytags where tag = '$tag'"; $r = serendipity_db_query($q); if ($r !== true) { echo $r; return false; } foreach ($entries as $entryid) { foreach ($newtags as $tag) { $q = "INSERT INTO ${serendipity['dbPrefix']}entrytags (entryid, tag) VALUES ('${entryid['entryid']}', '$tag')"; $r = serendipity_db_query($q); } } } function cleanupTagAssignments() { global $serendipity; if ($serendipity['version'][0] < 2) { echo "
    "; } // Search for inconsistencies $q_search = "SELECT et.tag AS tag, et.entryid AS entryid, e.id ". "FROM {$serendipity['dbPrefix']}entrytags AS et LEFT JOIN {$serendipity['dbPrefix']}entries AS e ". "ON et.entryid = e.id ". "WHERE e.id IS NULL ". "ORDER BY et.tag ASC"; $mappings = serendipity_db_query($q_search, FALSE, 'assoc', TRUE); if (is_array($mappings) && count($mappings) > 0) { // Inconsistencies found if ($this->eventData['GET']['perform'] == 'true') { // Perform cleanup $entryIDs = array(); foreach ($mappings as $mapping) { if (!in_array($mapping['entryid'], array_values($entryIDs))) { $entryIDs[] = $mapping['entryid']; } } $q_cleanup = "DELETE FROM {$serendipity['dbPrefix']}entrytags " . "WHERE entryid IN (".implode(", ", $entryIDs).")"; $cleanup = serendipity_db_query($q_cleanup); if ($cleanup === TRUE) { if ($serendipity['version'][0] < 2) { echo "".PLUGIN_EVENT_FREETAG_MANAGE_CLEANUP_SUCCESSFUL.""; } else { echo ' ' . PLUGIN_EVENT_FREETAG_MANAGE_CLEANUP_SUCCESSFUL . ''; } } else { if ($serendipity['version'][0] < 2) { echo "".PLUGIN_EVENT_FREETAG_MANAGE_CLEANUP_FAILED."

    DB-Error:".$cleanup; } else { echo '

    ' . PLUGIN_EVENT_FREETAG_MANAGE_CLEANUP_FAILED . '

    DB-Error: ' . $cleanup . '
    '; } } } else { // Show inconsistencies foreach ($mappings as $mapping) { $cleanup_tags[$mapping['tag']][] = $mapping['entryid']; } if ($serendipity['version'][0] < 2) { echo PLUGIN_EVENT_FREETAG_MANAGE_CLEANUP_INFO."

    "; } else { echo ' ' . PLUGIN_EVENT_FREETAG_MANAGE_CLEANUP_INFO . ''; } // Display list of found inconsistencies echo ""; echo ""; echo ""; foreach ($cleanup_tags as $tag => $entries) { echo ""; } echo "
    ".PLUGIN_EVENT_FREETAG_MANAGE_LIST_TAG."".PLUGIN_EVENT_FREETAG_MANAGE_CLEANUP_ENTRIES."
    $tag".implode(', ', $entries)."
    "; // Display submit form to start cleanup process echo '
    '; echo $this->getManageUrlAsHidden($this->eventData); echo ''; echo ''; if ($serendipity['version'][0] < 2) { echo ''; } else { echo ''; } echo '
    '; } } elseif ($mappings === TRUE) { // No inconsistencies found if ($serendipity['version'][0] < 2) { echo "".PLUGIN_EVENT_FREETAG_MANAGE_CLEANUP_NOTHING.""; } else { echo ' ' . PLUGIN_EVENT_FREETAG_MANAGE_CLEANUP_NOTHING . ''; } } else { // An error occures while searching for inconsistencies if ($serendipity['version'][0] < 2) { echo "".PLUGIN_EVENT_FREETAG_MANAGE_CLEANUP_LOOKUP_ERROR."

    DB-Error:".$mappings; } else { echo '

    ' . PLUGIN_EVENT_FREETAG_MANAGE_CLEANUP_LOOKUP_ERROR . '

    DB-Error: ' . $mappings . '
    '; } } } function addToCSS(&$eventData) { $eventData .= ' .serendipity_freeTag { margin-left: auto; margin-right: 0px; text-align: right; font-size: 7pt; display: block; margin-top: 5px; margin-bottom: 0px; } .serendipity_freeTag_related { margin-left: 50px; margin-right: 0px; text-align: left; font-size: small; display: block; margin-top: 20px; margin-bottom: 0px; } ' . (serendipity_db_bool($this->get_config('use_flash')) ? ' .serendipity_freetag_taglist { margin: 10px; border: 1px solid #' . $this->get_config('flash_tag_color', 'ffffff') . '; padding: 5px; background-color: #' . $this->get_config('flash_bg_color', 'ffffff') . '; text-align: justify; } ' : '') . ' .serendipity_freeTag a { font-size: 7pt; text-decoration: none; } .serendipity_freeTag a:hover { color: green; text-decoration: underline; } .serendipity_freeTag_xmlTagEntry { white-space: pre; } img.serendipity_freeTag_xmlButton { vertical-align: bottom; display: inline; border: 0px; } '; } function debugMsg($msg) { global $serendipity; $this->debug_fp = @fopen ( $serendipity ['serendipityPath'] . 'templates_c/freetag.log', 'a' ); if (! $this->debug_fp) { return false; } if (empty ( $msg )) { fwrite ( $this->debug_fp, "failure \n" ); } else { fwrite ( $this->debug_fp, print_r ( $msg, true ) ); } fclose ( $this->debug_fp ); } } /* vim: set sts=4 ts=4 expandtab : */