diff --git a/plugins/serendipity_event_karma/serendipity_event_karma.php b/plugins/serendipity_event_karma/serendipity_event_karma.php index 7979ffa2..801b19a3 100644 --- a/plugins/serendipity_event_karma/serendipity_event_karma.php +++ b/plugins/serendipity_event_karma/serendipity_event_karma.php @@ -13,7 +13,7 @@ if (file_exists($probelang)) { include dirname(__FILE__) . '/lang_en.inc.php'; -@define('PLUGIN_KARMA_DB_VERSION', '2.01'); +@define('PLUGIN_KARMA_DB_VERSION', '2.0'); class serendipity_event_karma extends serendipity_event { @@ -54,7 +54,7 @@ class serendipity_event_karma extends serendipity_event $propbag->add('description', PLUGIN_KARMA_BLAHBLAH); $propbag->add('stackable', false); $propbag->add('author', 'Garvin Hicking, Grischa Brockhaus, Gregor Völtz, Judebert'); - $propbag->add('version', '2.1'); + $propbag->add('version', '2.2'); $propbag->add('requirements', array( 'serendipity' => '0.8', 'smarty' => '2.6.7', @@ -65,6 +65,8 @@ class serendipity_event_karma extends serendipity_event 'entry_display' => true, 'css' => true, 'backend_header' => true, + 'backend_sidebar_entries' => true, + 'backend_sidebar_entries_event_display_karmalog' => true, 'event_additional_statistics' => true )); $propbag->add('groups', array('STATISTICS')); @@ -91,7 +93,7 @@ class serendipity_event_karma extends serendipity_event 'textual_visits', 'preview_bg', 'base_image', - // Text/Language optins + // Text/Language options 'text_tab', 'rate_msg', 'curr_msg', @@ -491,7 +493,6 @@ class serendipity_event_karma extends serendipity_event function event_hook($event, &$bag, &$eventData, $addData = null) { global $serendipity; - $hooks = &$bag->get('event_hooks'); @@ -558,8 +559,12 @@ class serendipity_event_karma extends serendipity_event return ; } - // We don't want googlebots hitting the karma-voting - if (stristr($_SERVER['HTTP_USER_AGENT'], 'google')) { + // We don't want bots hitting the karma-voting + $agent = $_SERVER['HTTP_USER_AGENT']; + if (stristr($agent, 'google') + || stristr($agent, 'LinkWalker') + || stristr($agent, 'zermelo') + || stristr($agent, 'NimbleCrawler')) { $this->karmaVote = 'invalid1'; return ; } @@ -1059,7 +1064,6 @@ END_IMG_CSS; //--TODO: Ensure that this works with the Custom Permalinks plugin // (We've seen trouble; it votes correctly, but redirects to the front page) $url = serendipity_currentURL(true); - // Voting is only allowed on entries. Therefore voting URLs must be // either single-entry URLs or summary URLs. serendipity_currentURL // converts them to an "ErrorDocument-URI", so we can focus on the @@ -1085,7 +1089,7 @@ END_IMG_CSS; // to this page after we cast our vote. // Remove any clutter from our previous voting activity - $url_parts = parse_url(serendipity_currentURL()); + $url_parts = parse_url(serendipity_currentURL(true)); if (!empty($url_parts['query'])) { $exclude = array('serendipity[karmaVote]', 'serendipity[karmaId]'); // I tried using parse_str, but it gave me very weird results @@ -1275,6 +1279,343 @@ END_IMG_CSS; return true; break; + // Display the Karma Log link on the sidebar + case 'backend_sidebar_entries': +?> + +$msg\n"); + //} + // Was I asked to process any votes? + if (($serendipity['POST']['delete_button'] || $serendipity['POST']['approve_button']) + && sizeof($serendipity['POST']['delete']) != 0 && serendipity_checkFormToken()) { + foreach($serendipity['POST']['delete'] as $d => $i) { + $kdata = $serendipity['POST']['karmalog'.$i]; + // validate posted variables + // posted points + $ppoints = $kdata['points']; + if (!is_numeric($ppoints) || ((int)$ppoints < -2) || ((int)$ppoints > 2)) { + print("
".PLUGIN_KARMA_INVALID_INPUT."
\n"); + return false; + } + // posted id + $pid = $kdata['entryid']; + if (!is_numeric($pid)) { + print("
".PLUGIN_KARMA_INVALID_INPUT."
\n"); + return false; + } + // posted IP + $pip = long2ip(ip2long($kdata['ip'])); + if ($pip == -1 || $pip === FALSE) { + print("
".PLUGIN_KARMA_INVALID_INPUT."
\n"); + return false; + } + // posted user agent (need a better validator, I think) + $puser_agent = $kdata['user_agent']; + if (serendipity_db_escape_string($puser_agent) != $puser_agent) { + print("
".PLUGIN_KARMA_INVALID_INPUT."
\n"); + return false; + } + // posted vote time + $pvotetime = $kdata['votetime']; + $unixsecs = date('U', $kdata['votetime']); + if ($pvotetime != $unixsecs) { + print("
".PLUGIN_KARMA_INVALID_INPUT."
\n"); + return false; + } + + // Remove karma from entry? + if ($serendipity['POST']['delete_button']) { + // Fetch vote total for the entry IDs + $q = 'SELECT k.* + FROM ' . $serendipity['dbPrefix'] . 'karma AS k + WHERE k.entryid IN (' . $pid . ') GROUP BY k.entryid'; + + $sql = serendipity_db_query($q); + if (is_array($sql)) { + $karma = $sql[0]; + + $update = sprintf( + "UPDATE {$serendipity['dbPrefix']}karma + SET points = %s, + votes = %s + WHERE entryid = %s", + serendipity_db_escape_string($karma['points'] - $ppoints), + serendipity_db_escape_string($karma['votes'] - 1), + serendipity_db_escape_string($pid) + ); + $updated = serendipity_db_query($update); + if ($updated != 1) { + printf("
".PLUGIN_KARMA_REMOVE_ERROR."
\n", $pid); + // Don't delete from karma log if we couldn't take away the points + continue; + } + } else { + // This will only happen if someone is messing with the karma table or submit data + printf("
".PLUGIN_KARMA_UPDATE_ERROR."
", $pid); + continue; + } + } + + // Remove vote from log (approved or deleted, doesn't matter) + $del = sprintf( + "DELETE FROM {$serendipity['dbPrefix']}karmalog + WHERE entryid = %s AND ip = '%s' AND user_agent LIKE '%%%s%%' AND votetime = %s LIMIT 1", + serendipity_db_escape_string($pid), + serendipity_db_escape_string($pip), + serendipity_db_escape_string($puser_agent), + serendipity_db_escape_string($pvotetime) + ); + $deleted = serendipity_db_query($del); + // User feedback + if ($deleted == 1) { + if ($serendipity['POST']['delete_button']) { + printf("
".PLUGIN_KARMA_REMOVED_POINTS."
\n", $ppoints, $pid); + } else { + printf("
".PLUGIN_KARMA_APPROVED_POINTS."
\n", $ppoints, $pid); + } + } else { + printf("
".PLUGIN_KARMA_REMOVE_ERROR."
\n", $pid); + } + } + } + + // URL; expected to be event_display and karmalog, respectively + $url = '?serendipity[adminModule]='.$serendipity['GET']['adminModule'].'&serendipity[adminAction]='.$serendipity['GET']['adminAction']; + + // Filters + print(" +
+ + + + + + + + + + + + + + + + + + +
".FILTERS."
User Agent:".IP."
Entry ID:Entry title:
+"); + // Set all filters into $and and $searchString + if (!empty($serendipity['GET']['filter']['entryid'])) { + $val = $serendipity['GET']['filter']['entryid']; + $and .= "AND l.entryid = '" . serendipity_db_escape_string($val) . "'"; + $searchString .= "&serendipity['filter']['entryid']=".htmlspecialchars($val); + } + if (!empty($serendipity['GET']['filter']['ip'])) { + $val = $serendipity['GET']['filter']['ip']; + $and .= "AND l.ip = '" . serendipity_db_escape_string($val) . "'"; + $searchString .= "&serendipity['filter']['ip']=".htmlspecialchars($val); + } + if (!empty($serendipity['GET']['filter']['user_agent'])) { + $val = $serendipity['GET']['filter']['user_agent']; + $and .= "AND l.user_agent LIKE '%" . serendipity_db_escape_string($val) . "%'"; + $searchString .= "&serendipity['filter']['user_agent']=".htmlspecialchars($val); + } + if (!empty($serendipity['GET']['filter']['title'])) { + $val = $serendipity['GET']['filter']['title']; + $and .= "AND e.title LIKE '%" . serendipity_db_escape_string($val) . "%'"; + $searchString .= "&serendipity['filter']['title']=".htmlspecialchars($val); + } + + // Sorting (controls go after filtering controls in form above) + $sort_order = array( + 'votetime' => DATE, + 'user_agent' => USER_AGENT, + 'title' => TITLE, + 'entryid' => 'ID'); + if (empty($serendipity['GET']['sort']['ordermode']) || $serendipity['GET']['sort']['ordermode'] != 'ASC') { + $desc = true; + $serendipity['GET']['sort']['ordermode'] = 'DESC'; + } + if (!empty($serendipity['GET']['sort']['order']) && !empty($sort_order[$serendipity['GET']['sort']['order']])) { + $curr_order = $serendipity['GET']['sort']['order']; + $orderby = serendipity_db_escape_string($curr_order . ' ' . $serendipity['GET']['sort']['ordermode']); + } else { + $curr_order = 'votetime'; + $orderby = 'votetime ' . serendipity_db_escape_string($serendipity['GET']['sort']['ordermode']); + } + print(" +
".SORT_BY." + + +
+ +
+"); + + // Paging (partly ripped from include/admin/comments.inc.php) + $commentsPerPage = (int)(!empty($serendipity['GET']['filter']['perpage']) ? $serendipity['GET']['filter']['perpage'] : 25); + $sql = serendipity_db_query("SELECT COUNT(*) AS total FROM {$serendipity['dbPrefix']}karmalog l WHERE 1 = 1 " . $and, true); + $totalVotes = $sql['total']; + $pages = ($commentsPerPage == COMMENTS_FILTER_ALL ? 1 : ceil($totalVotes/(int)$commentsPerPage)); + $page = (int)$serendipity['GET']['page']; + if ($page == 0 || ($page > $pages)) { + $page = 1; + } + + if ($page > 1) { + $linkPrevious = $url . '&serendipity[page]='. ($page-1) . $searchString; + } + if ($pages > $page) { + $linkNext = $url . '&serendipity[page]='. ($page+1) . $searchString; + } + + if ($commentsPerPage == COMMENTS_FILTER_ALL) { + $limit = ''; + }else { + $limit = serendipity_db_limit_sql(serendipity_db_limit(($page-1)*(int)$commentsPerPage, (int)$commentsPerPage)); + } + + // Variables for display + if ($linkPrevious) { + $linkPrevious = ''; + } else { + $linkPrevious = ' '; + } + if ($linkNext) { + $linkNext = ''; + } else { + $linkNext = ' '; + } + $paging = sprintf(PAGE_BROWSE_COMMENTS, $page, $pages, $totalVotes); + + // Retrieve the next batch of karma votes + // [entryid, points, ip, user_agent, votetime] + $sql = serendipity_db_query("SELECT l.entryid AS entryid, l.points AS points, l.ip AS ip, l.user_agent AS user_agent, l.votetime AS votetime, e.title AS title FROM {$serendipity['dbPrefix']}karmalog l + LEFT JOIN {$serendipity['dbPrefix']}entries e ON (e.id = l.entryid) + WHERE 1 = 1 " . $and . " + ORDER BY $orderby $limit"); + + // Start the form for display and deleting + if (is_array($sql)) { + print("
\n".serendipity_setFormToken()." + +"); + + // Print the header paging table + print(" + + + + + + +
$linkPrevious$paging$linkNext
+"); + // Start the vote table + print(" + +"); + // Print each vote + $i = 0; + foreach ($sql as $vote) { + $i++; + // entryid, title, points, ip, user_agent, votetime + $entrylink = serendipity_archiveURL($vote['entryid'], $vote['title'], 'serendipityHTTPPath', true); + $entryFilterHtml = ""; + $ipFilterHtml = ""; + $timestr = strftime('%H:%M:%S
%n%a %b %d %Y', $vote['votetime']); + $cssClass = 'serendipity_admin_list_item serendipity_admin_list_item_'; + $cssClass .= (($i % 2 ==0)?'even':'uneven'); + $barClass = str_replace(array('.',' '), array('_','_'), $this->image_name); + $barHtml = $this->createRatingBar(null, $vote['points'], 1, $barClass); + $barHtml = sprintf($barHtml, 'what', $vote['points'], '1'); + print(" + + + + + + + + + + +"); + } + + // End the vote table + print(" +
+ + + + + + + $barHtml{$vote['title']} $entryFilterHtml
$timestr{$vote['ip']} $ipFilterHtml{$vote['user_agent']}
+ "); + if (is_array($sql)) { + print(" + + + +
+"); + } + + // Print the footer paging table + print(" + + + + + + +
$linkPrevious$paging$linkNext
+"); + } else { + print(" +
No entries to display.
+"); + } + + return true; + break; + default: return false; }// End switch on event hooks @@ -1645,7 +1986,6 @@ END_IMG_CSS; } elseif ($rating <= -0.5) { $rating = PLUGIN_KARMA_VOTEPOINT_2; } elseif ($rating <= 0.5) { - $rating = PLUGIN_KARMA_VOTEPOINT_3; } elseif ($rating <= 1.5) { $rating = PLUGIN_KARMA_VOTEPOINT_4; } else {