<?php /* Plugin Name: Badges Plugin URI: https://github.com/NoahY/q2a-badges Plugin Description: Awards Badges Plugin Version: 4.8 Plugin Date: 2011-07-30 Plugin Author: NoahY Plugin Author URI: Plugin License: GPLv3+ Plugin Minimum Question2Answer Version: 1.5 Plugin Update Check URI: https://raw.github.com/NoahY/q2a-badges/master/qa-plugin.php */ if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser header('Location: ../../'); exit; } qa_register_plugin_module('event', 'qa-badge-check.php','badge_check','Badge Check'); qa_register_plugin_module('module', 'qa-badge-admin.php', 'qa_badge_admin', 'Badge Admin'); qa_register_plugin_module('page', 'qa-badge-page.php', 'qa_badge_page', 'Badges'); qa_register_plugin_module('widget', 'qa-badge-widget.php', 'qa_badge_widget', 'Recent Badge Widget'); qa_register_plugin_layer('qa-badge-layer.php', 'Badge Notification Layer'); qa_register_plugin_phrases('qa-badge-lang-*.php', 'badges'); function qa_badge_lang($string) { return qa_lang($string); } function qa_get_badge_list() { // badges - add to this list to add a new badge, it will be imported when you run this function. Don't change existing slugs! $badges = array(); if(!QA_FINAL_EXTERNAL_USERS) { $badges['verified'] = array('type'=>0); $badges['profiler'] = array('type'=>0); $badges['avatar'] = array('type'=>0); } $badges['nice_question'] = array('var'=>2, 'type'=>0); $badges['good_question'] = array('var'=>5, 'type'=>1); $badges['great_question'] = array('var'=>10, 'type'=>2); $badges['notable_question'] = array('var'=>50, 'type'=>0); $badges['popular_question'] = array('var'=>100, 'type'=>1); $badges['famous_question'] = array('var'=>500, 'type'=>2); $badges['nice_answer'] = array('var'=>2, 'type'=>0); $badges['good_answer'] = array('var'=>5, 'type'=>1); $badges['great_answer'] = array('var'=>10, 'type'=>2); $badges['nice_answer_old'] = array('var'=>30, 'type'=>0); $badges['good_answer_old'] = array('var'=>60, 'type'=>1); $badges['great_answer_old'] = array('var'=>120, 'type'=>2); $badges['gifted'] = array('var'=>1, 'type'=>0); $badges['wise'] = array('var'=>10, 'type'=>1); $badges['enlightened'] = array('var'=>30, 'type'=>2); $badges['grateful'] = array('var'=>1, 'type'=>0); $badges['respectful'] = array('var'=>20, 'type'=>1); $badges['reverential'] = array('var'=>50, 'type'=>2); $badges['liked'] = array('var'=>20, 'type'=>0); $badges['loved'] = array('var'=>50, 'type'=>1); $badges['revered'] = array('var'=>200, 'type'=>2); $badges['asker'] = array('var'=>10, 'type'=>0); $badges['questioner'] = array('var'=>25, 'type'=>1); $badges['inquisitor'] = array('var'=>50, 'type'=>2); $badges['answerer'] = array('var'=>25, 'type'=>0); $badges['lecturer'] = array('var'=>50, 'type'=>1); $badges['preacher'] = array('var'=>100, 'type'=>2); $badges['commenter'] = array('var'=>50, 'type'=>0); $badges['commentator'] = array('var'=>100, 'type'=>1); $badges['annotator'] = array('var'=>500, 'type'=>2); $badges['voter'] = array('var'=>10, 'type'=>0); $badges['avid_voter'] = array('var'=>50, 'type'=>1); $badges['devoted_voter'] = array('var'=>200, 'type'=>2); $badges['editor'] = array('var'=>1, 'type'=>0); $badges['copy_editor'] = array('var'=>15, 'type'=>1); $badges['senior_editor'] = array('var'=>50, 'type'=>2); $badges['watchdog'] = array('var'=>1, 'type'=>0); $badges['bloodhound'] = array('var'=>10, 'type'=>1); $badges['pitbull'] = array('var'=>30, 'type'=>2); $badges['reader'] = array('var'=>20, 'type'=>0); $badges['avid_reader'] = array('var'=>50, 'type'=>1); $badges['devoted_reader'] = array('var'=>200, 'type'=>2); $badges['dedicated'] = array('var'=>10, 'type'=>0); $badges['devoted'] = array('var'=>25, 'type'=>1); $badges['zealous'] = array('var'=>50, 'type'=>2); $badges['visitor'] = array('var'=>30, 'type'=>0); $badges['trouper'] = array('var'=>100, 'type'=>1); $badges['veteran'] = array('var'=>200, 'type'=>2); $badges['regular'] = array('var'=>90, 'type'=>0); $badges['old_timer'] = array('var'=>180, 'type'=>1); $badges['ancestor'] = array('var'=>365, 'type'=>2); $badges['100_club'] = array('var'=>100, 'type'=>0); $badges['1000_club'] = array('var'=>1000, 'type'=>1); $badges['10000_club'] = array('var'=>10000, 'type'=>2); $badges['medalist'] = array('var'=>10, 'type'=>0); $badges['champion'] = array('var'=>30, 'type'=>1); $badges['olympian'] = array('var'=>100, 'type'=>2); // get badges from other plugins - experimental! $moduletypes=qa_list_module_types(); foreach ($moduletypes as $moduletype) { $modulenames=qa_list_modules($moduletype); foreach ($modulenames as $modulename) { $module=qa_load_module($moduletype, $modulename); if (method_exists($module, 'custom_badges')) $badges=array_merge($badges,$module->custom_badges()); } } return $badges; } function qa_get_badges_by_type() { $bin = qa_get_badge_list(); foreach($bin as $slug => $info) { $bout[$info['type']][] = array( 'slug'=>$slug, 'var'=>@$info['var'] ); } return $bout; } function qa_get_badge_type_by_slug($slug) { $badges = qa_get_badge_list(); return qa_get_badge_type(@$badges[$slug]['type']); } function qa_get_badge_type($id) { // badge categories, e.g. bronze, silver, gold $badge_types = array(); $badge_types[] = array('slug'=>'bronze','name'=>qa_lang('badges/bronze')); $badge_types[] = array('slug'=>'silver','name'=>qa_lang('badges/silver')); $badge_types[] = array('slug'=>'gold','name'=>qa_lang('badges/gold')); $id = (int)$id; return $badge_types[$id]; } function qa_badge_award_check($badges, $var, $uid, $oid = NULL, $notify = 1) { // oid is the postid (if), notify = 1 for email and popup, 2 for just popup. if(!$uid) return; $awarded = array(); foreach($badges as $badge_slug) { if(($var === false || (int)$var >= (int)qa_opt('badge_'.$badge_slug.'_var')) && qa_opt('badge_'.$badge_slug.'_enabled') !== '0') { if($oid) { $result = @qa_db_read_one_value( qa_db_query_sub( 'SELECT badge_slug FROM ^userbadges WHERE user_id=# AND badge_slug=$ AND object_id=#', $uid, $badge_slug, $oid ), true ); } else { $result = @qa_db_read_one_value( qa_db_query_sub( 'SELECT badge_slug FROM ^userbadges WHERE user_id=# AND badge_slug=$', $uid, $badge_slug ), true ); } if ($result == null) { // not already awarded this badge qa_db_query_sub( 'INSERT INTO ^userbadges (awarded_at, notify, object_id, user_id, badge_slug, id) '. 'VALUES (NOW(), #, #, #, #, 0)', $notify, $oid, $uid, $badge_slug ); if($notify > 0) { //qa_db_usernotice_create($uid, $content, 'html'); if(qa_opt('badge_email_notify') && $notify == 1) qa_badge_notification($uid, $oid, $badge_slug); if(qa_opt('event_logger_to_database')) { // add event $handle = qa_getHandleFromId($uid); qa_db_query_sub( 'INSERT INTO ^eventlog (datetime, ipaddress, userid, handle, cookieid, event, params) '. 'VALUES (NOW(), $, $, $, #, $, $)', qa_remote_ip_address(), $uid, $handle, qa_cookie_get(), 'badge_awarded', 'badge_slug='.$badge_slug.($oid?"\t".'postid='.$oid:'') ); } } array_push($awarded,$badge_slug); } } } return $awarded; } function qa_badge_notification($uid, $oid, $badge_slug) { if(!qa_opt('badge_email_notify_id_'.$uid)) return; require_once QA_INCLUDE_DIR.'qa-app-users.php'; require_once QA_INCLUDE_DIR.'qa-app-emails.php'; if (QA_FINAL_EXTERNAL_USERS) { $publictohandle=qa_get_public_from_userids(array($uid)); $handle=@$publictohandle[$uid]; } else { $user = qa_db_single_select(qa_db_user_account_selectspec($uid, true)); $handle = @$user['handle']; } $subject = qa_opt('badge_email_subject'); $body = qa_opt('badge_email_body'); $body = preg_replace('/\^if_post_text="([^"]*)"/',($oid?'$1':''),$body); // if post text $site_url = qa_opt('site_url'); $profile_url = qa_path_html('user/'.$handle, null, $site_url); if($oid) { $post = qa_db_read_one_assoc( qa_db_query_sub( 'SELECT * FROM ^posts WHERE postid=#', $oid ), true ); if($post['parentid']) $parent = qa_db_read_one_assoc( qa_db_query_sub( 'SELECT * FROM ^posts WHERE postid=#', $post['parentid'] ), true ); if(isset($parent) && $parent['basetype'] == 'A') { $parent = qa_db_read_one_assoc( qa_db_query_sub( 'SELECT * FROM ^posts WHERE postid=#', $parent['parentid'] ), true ); } if(isset($parent)) { $anchor = urlencode(qa_anchor($post['basetype'], $oid)); $post_title = $parent['title']; $post_url = qa_path_html(qa_q_request($parent['postid'], $parent['title']), null, qa_opt('site_url'),null, $anchor); } else { $post_title = $post['title']; $post_url = qa_path_html(qa_q_request($post['postid'], $post['title']), null, qa_opt('site_url')); } } $subs = array( '^badge_name'=> qa_opt('badge_'.$badge_slug.'_name'), '^post_title'=> @$post_title, '^post_url'=> @$post_url, '^profile_url'=> $profile_url, '^site_url'=> $site_url, ); qa_send_notification($uid, '@', $handle, $subject, $body, $subs); } function qa_badge_name($slug,$reset=false) { if($reset) $name = qa_lang('badges/'.$slug); else $name = qa_opt('badge_'.$slug.'_name')?qa_opt('badge_'.$slug.'_name'):qa_lang('badges/'.$slug); // plugins if($name == '[badges/'.$slug.']') { global $qa_lang_file_pattern; foreach($qa_lang_file_pattern as $name => $files) { $lang = qa_lang($name.'/badge_'.$slug); if($lang != '['.$name.'/badge_'.$slug.']') { return $lang; } } return $slug; } return $name; } function qa_badge_desc_replace($slug,$var=null,$admin=false) { $desc = qa_opt('badge_'.$slug.'_desc')?qa_opt('badge_'.$slug.'_desc'):qa_lang('badges/'.$slug.'_desc'); // plugins if($desc == '[badges/'.$slug.'_desc]') { global $qa_lang_file_pattern; foreach($qa_lang_file_pattern as $name => $files) { $lang = qa_lang($name.'/badge_'.$slug.'_desc'); if($lang != '['.$name.'/badge_'.$slug.'_desc]') { $desc = $lang; break; } } } // var replace if($var) { $desc = $admin?str_replace('#','<input type="text" name="badge_'.$slug.'_var" size="4" value="'.$var.'">',$desc):str_replace('#',$var,$desc); $desc = preg_replace('/\^([^^]+)\^(\S+)/',($var == 1?"$1":"$2"),$desc); } // other badge reference replace preg_match_all('|\$(\S+)|',$desc,$others,PREG_SET_ORDER); if(!$others) return $desc; foreach($others as $other) { if(!qa_opt('badge_'.$other[1].'_name')) qa_opt('badge_'.$other[1].'_name',qa_lang('badges/'.$other[1])); $name = qa_opt('badge_'.$other[1].'_name'); $desc = str_replace($other[0],$name,$desc); } return $desc; } if(!function_exists('qa_getHandleFromId')) { function qa_getHandleFromId($userid) { require_once QA_INCLUDE_DIR.'qa-app-users.php'; if (QA_FINAL_EXTERNAL_USERS) { $publictohandle=qa_get_public_from_userids(array($userid)); $handle=@$publictohandle[$userid]; } else { $user = qa_db_single_select(qa_db_user_account_selectspec($userid, true)); $handle = @$user['handle']; } return $handle; } } // worker functions // layout function qa_badge_plugin_user_widget($handle) { $userids = qa_handles_to_userids(array($handle)); $userid = $userids[$handle]; // displays small badge widget, suitable for meta $result = qa_db_read_all_values( qa_db_query_sub( 'SELECT badge_slug FROM ^userbadges WHERE user_id=#', $userid ) ); if(count($result) == 0) return; $badges = qa_get_badge_list(); foreach($result as $slug) { $bcount[$badges[$slug]['type']] = isset($bcount[$badges[$slug]['type']])?$bcount[$badges[$slug]['type']]+1:1; } $output='<span id="badge-medals-widget">'; for($x = 2; $x >= 0; $x--) { if(!isset($bcount[$x])) continue; $count = $bcount[$x]; if($count == 0) continue; $type = qa_get_badge_type($x); $types = $type['slug']; $typed = $type['name']; $output.='<span class="badge-pointer badge-'.$types.'-medal" title="'.$count.' '.$typed.'">●</span><span class="badge-pointer badge-'.$types.'-count" title="'.$count.' '.$typed.'"> '.$count.'</span> '; } $output = substr($output,0,-1); // lazy remove space $output.='</span>'; return($output); } function qa_badge_plugin_user_form($userid) { $handles = qa_userids_to_handles(array($userid)); $handle = $handles[$userid]; // displays badge list in user profile $result = qa_db_read_all_assoc( qa_db_query_sub( 'SELECT badge_slug as slug, object_id AS oid FROM ^userbadges WHERE user_id=#', $userid ) ); $fields = array(); if(count($result) > 0) { // count badges $bin = qa_get_badge_list(); $badges = array(); foreach($result as $info) { $slug = $info['slug']; $type = $bin[$slug]['type']; if(isset($badges[$type][$slug])) $badges[$type][$slug]['count']++; else $badges[$type][$slug]['count'] = 1; if($info['oid']) $badges[$type][$slug]['oid'][] = $info['oid']; } foreach($badges as $type => $badge) { $typea = qa_get_badge_type($type); $types = $typea['slug']; $typed = $typea['name']; $output = ' <table> <tr> <td class="qa-form-wide-label"> <h3 class="badge-title" title="'.qa_lang('badges/'.$types.'_desc').'">'.$typed.'</h3> </td> </tr>'; foreach($badge as $slug => $info) { $badge_name=qa_badge_name($slug); if(!qa_opt('badge_'.$slug.'_name')) qa_opt('badge_'.$slug.'_name',$badge_name); $name = qa_opt('badge_'.$slug.'_name'); $count = $info['count']; if(qa_opt('badge_show_source_posts')) { $oids = @$info['oid']; } else $oids = null; $var = qa_opt('badge_'.$slug.'_var'); $desc = qa_badge_desc_replace($slug,$var,false); // badge row $output .= ' <tr> <td class="badge-container"> <div class="badge-container-badge"> <span class="badge-'.$types.'" title="'.$desc.' ('.$typed.')">'.qa_html($name).'</span> <span onclick="jQuery(\'.badge-container-sources-'.$slug.'\').slideToggle()" class="badge-count'.(is_array($oids)?' badge-count-link" title="'.qa_lang('badges/badge_count_click'):'').'">x '.$count.'</span> </div>'; // source row(s) if any if(is_array($oids)) { $output .= ' <div class="badge-container-sources-'.$slug.'" style="display:none">'; foreach($oids as $oid) { $post = qa_db_select_with_pending( qa_db_full_post_selectspec(null, $oid) ); $title=$post['title']; $anchor = ''; if($post['parentid']) { $anchor = urlencode(qa_anchor($post['type'],$oid)); $oid = $post['parentid']; $title = qa_db_read_one_value( qa_db_query_sub( 'SELECT BINARY title as title FROM ^posts WHERE postid=#', $oid ), true ); } $length = 30; $text = (qa_strlen($title) > $length ? qa_substr($title,0,$length).'...' : $title); $output .= ' <div class="badge-source"><a href="'.qa_path_html(qa_q_request($oid,$title),NULL,qa_opt('site_url')).($anchor?'#'.$anchor:'').'">'.qa_html($text).'</a></div>'; } $output .= '</div>'; } $output .= ' </td> </tr>'; } $output .= ' </table>'; $outa[] = $output; } $fields[] = array( 'value' => '<table class="badge-user-tables"><tr><td class="badge-user-table">'.implode('</td><td class="badge-user-table">',$outa).'</td></tr></table>', 'type' => 'static', ); } $ok = null; $tags = null; $buttons = array(); if((bool)qa_opt('badge_email_notify') && qa_get_logged_in_handle() == $handle) { // add badge notify checkbox if(qa_clicked('badge_email_notify_save')) { qa_opt('badge_email_notify_id_'.$userid, (bool)qa_post_text('badge_notify_email_me')); $ok = qa_lang('badges/badge_notified_email_me'); } $select = (bool)qa_opt('badge_email_notify_id_'.$userid); $tags = 'id="badge-form" action="'.qa_self_html().'#signature_text" method="POST"'; $fields[] = array( 'type' => 'blank', ); $fields[] = array( 'label' => qa_lang('badges/badge_notify_email_me'), 'type' => 'checkbox', 'tags' => 'NAME="badge_notify_email_me"', 'value' => $select, ); $buttons[] = array( 'label' => qa_lang_html('main/save_button'), 'tags' => 'NAME="badge_email_notify_save"', ); } return array( 'ok' => ($ok && !isset($error)) ? $ok : null, 'style' => 'tall', 'tags' => $tags, 'title' => qa_lang('badges/badges'), 'fields'=>$fields, 'buttons'=>$buttons, ); } /* Omit PHP closing tag to help avoid accidental output */