Commit afab146b by Gideon Greenspan

1.5-beta-2

parent 2c5a8c70
DirectoryIndex index.php
<IfModule mod_rewrite.c>
RewriteEngine On
#RewriteBase /your-sub-directory
#RewriteBase /
RewriteCond %{REQUEST_URI} ^(.*)//(.*)$
RewriteRule . %1/%2 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ index.php?qa-rewrite=$0&%{QUERY_STRING} [L]
</IfModule>
......@@ -317,8 +317,9 @@
qa_get_userids_from_public($publicusernames)
You should take the array of public usernames in $publicusernames, and return an array which
maps those usernames to internal user ids. For each element of this array, the username you
were given should be in the key, with the corresponding user id in the value.
maps valid usernames to internal user ids. For each element of this array, the username should be
in the key, with the corresponding user id in the value. If your usernames are case- or accent-
insensitive, keys should contain the usernames as stored, not necessarily as in $publicusernames.
Call qa_db_connection() to get the connection to the Q2A database. If your database is shared with
Q2A, you can use this with PHP's MySQL functions such as mysql_query() to run queries. If you
......@@ -384,8 +385,8 @@
This is exactly like qa_get_userids_from_public(), but works in the other direction.
You should take the array of user identifiers in $userids, and return an array which maps
those to public usernames. For each element of this array, the userid you were given should
You should take the array of user identifiers in $userids, and return an array which maps valid
userids to public usernames. For each element of this array, the userid you were given should
be in the key, with the corresponding username in the value.
Call qa_db_connection() to get the connection to the Q2A database. If your database is shared with
......
......@@ -42,7 +42,7 @@
// Load relevant information about this question and check it exists
$usecaptcha=qa_user_use_captcha('captcha_on_anon_post');
$usecaptcha=qa_user_use_captcha();
$questionid=qa_post_text('a_questionid');
$userid=qa_get_logged_in_userid();
......
......@@ -40,11 +40,10 @@
require_once QA_INCLUDE_DIR.'qa-page-question-submit.php';
require_once QA_INCLUDE_DIR.'qa-util-sort.php';
$usecaptcha=qa_user_use_captcha('captcha_on_anon_post');
// Load relevant information about this question and check it exists
$usecaptcha=qa_user_use_captcha();
$questionid=qa_post_text('c_questionid');
$parentid=qa_post_text('c_parentid');
$userid=qa_get_logged_in_userid();
......
......@@ -398,7 +398,7 @@
} elseif (@$post['uservote']>0) {
$fields['vote_state']='voted_up';
$fields['vote_up_tags']='TITLE="'.qa_lang_html('main/voted_up_popup').'" NAME="'.qa_html('vote_'.$postid.'_0_'.$elementid).'"'.$onclick;
$fields['vote_up_tags']='TITLE="'.qa_lang_html('main/voted_up_popup').'" NAME="'.qa_html('vote_'.$postid.'_0_'.$elementid).'" '.$onclick;
$fields['vote_down_tags']=' ';
} elseif (@$post['uservote']<0) {
......@@ -460,9 +460,9 @@
$fields['who']['level']=qa_html(qa_user_level_string($post['level']));
}
if ((!QA_FINAL_EXTERNAL_USERS) && (@$options['avatarsize']>0) && isset($post['flags']))
$fields['avatar']=qa_get_user_avatar_html($post['flags'], $post['email'], $post['handle'],
$post['avatarblobid'], $post['avatarwidth'], $post['avatarheight'], $options['avatarsize']);
if ((!QA_FINAL_EXTERNAL_USERS) && (@$options['avatarsize']>0))
$fields['avatar']=qa_get_user_avatar_html(@$post['flags'], @$post['email'], @$post['handle'],
@$post['avatarblobid'], @$post['avatarwidth'], @$post['avatarheight'], $options['avatarsize']);
// Updated when and by whom
......@@ -1354,7 +1354,7 @@
'<SPAN ID="'.$fieldprefix.'email_shown">'.$labelaskemail.'</SPAN>'.
'<SPAN ID="'.$fieldprefix.'email_hidden" STYLE="display:none;">'.$labelonly.'</SPAN>';
$fields['notify']['tags'].='ID="'.$fieldprefix.'notify" onclick="if (document.getElementById(\''.$fieldprefix.'notify\').checked) document.getElementById(\''.$fieldprefix.'email\').focus();"';
$fields['notify']['tags'].=' ID="'.$fieldprefix.'notify" onclick="if (document.getElementById(\''.$fieldprefix.'notify\').checked) document.getElementById(\''.$fieldprefix.'email\').focus();"';
$fields['notify']['tight']=true;
$fields['email']=array(
......@@ -1581,6 +1581,21 @@
}
function qa_update_post_text(&$fields, $oldfields)
/*
Check if any of the 'content', 'format' or 'text' elements have changed between $oldfields and $fields
If so, recalculate $fields['text'] based on $fields['content'] and $fields['format']
*/
{
if (
strcmp($oldfields['content'], $fields['content']) ||
strcmp($oldfields['format'], $fields['format']) ||
strcmp($oldfields['text'], $fields['text'])
)
$fields['text']=qa_viewer_text($fields['content'], $fields['format']);
}
function qa_get_avatar_blob_html($blobid, $width, $height, $size, $padding=false)
/*
Return the <IMG...> HTML to display avatar $blobid whose stored size is $width and $height
......
......@@ -68,7 +68,7 @@
if (!$queued) {
qa_db_category_path_qcount_update(qa_db_post_get_category_path($postid));
qa_post_index($postid, 'Q', $postid, @$followanswer['postid'], $title, $content, $format, $text, $tagstring);
qa_post_index($postid, 'Q', $postid, @$followanswer['postid'], $title, $content, $format, $text, $tagstring, $categoryid);
qa_db_points_update_ifuser($userid, 'qposts');
qa_db_qcount_update();
qa_db_unaqcount_update();
......@@ -122,10 +122,10 @@
}
function qa_post_index($postid, $type, $questionid, $parentid, $title, $content, $format, $text, $tagstring)
function qa_post_index($postid, $type, $questionid, $parentid, $title, $content, $format, $text, $tagstring, $categoryid)
/*
Add post $postid (which comes under $questionid) of $type (Q/A/C) to the database index, with $title, $text
and $tagstring. Calls through to all installed search modules.
Add post $postid (which comes under $questionid) of $type (Q/A/C) to the database index, with $title, $text,
$tagstring and $categoryid. Calls through to all installed search modules.
*/
{
global $qa_post_indexing_suspended;
......@@ -137,7 +137,7 @@
$searches=qa_load_modules_with('search', 'index_post');
foreach ($searches as $search)
$search->index_post($postid, $type, $questionid, $parentid, $title, $content, $format, $text, $tagstring);
$search->index_post($postid, $type, $questionid, $parentid, $title, $content, $format, $text, $tagstring, $categoryid);
}
......@@ -155,7 +155,7 @@
if (!$queued) {
if ($question['type']=='Q') // don't index answer if parent question is hidden or queued
qa_post_index($postid, 'A', $question['postid'], $question['postid'], null, $content, $format, $text, null);
qa_post_index($postid, 'A', $question['postid'], $question['postid'], null, $content, $format, $text, null, $question['categoryid']);
qa_db_post_acount_update($question['postid']);
qa_db_hotness_update($question['postid']);
......@@ -205,7 +205,7 @@
if (!$queued) {
if ( ($question['type']=='Q') && (($parent['type']=='Q') || ($parent['type']=='A')) ) // only index if antecedents fully visible
qa_post_index($postid, 'C', $question['postid'], $parent['postid'], null, $content, $format, $text, null);
qa_post_index($postid, 'C', $question['postid'], $parent['postid'], null, $content, $format, $text, null, $question['categoryid']);
qa_db_points_update_ifuser($userid, 'cposts');
qa_db_ccount_update();
......
......@@ -62,7 +62,7 @@
}
if ($oldquestion['type']=='Q') // not hidden or queued
qa_post_index($oldquestion['postid'], 'Q', $oldquestion['postid'], $oldquestion['parentid'], $title, $content, $format, $text, $tagstring);
qa_post_index($oldquestion['postid'], 'Q', $oldquestion['postid'], $oldquestion['parentid'], $title, $content, $format, $text, $tagstring, $oldquestion['categoryid']);
qa_report_event('q_edit', $userid, $handle, $cookieid, array(
'postid' => $oldquestion['postid'],
......@@ -180,7 +180,7 @@
qa_db_posts_calc_category_path($postid);
if ($oldquestion['type']=='Q')
qa_post_index($postid, 'NOTE', $oldquestion['postid'], $oldquestion['postid'], null, $note, '', $note, null);
qa_post_index($postid, 'NOTE', $oldquestion['postid'], $oldquestion['postid'], null, $note, '', $note, null, $oldquestion['categoryid']);
qa_db_post_set_closed($oldquestion['postid'], $postid, $userid, qa_remote_ip_address());
......@@ -233,13 +233,13 @@
qa_db_unupaqcount_update();
if (!$hidden) {
qa_post_index($oldquestion['postid'], 'Q', $oldquestion['postid'], $oldquestion['parentid'], $oldquestion['title'],
$oldquestion['content'], $oldquestion['format'], qa_viewer_text($oldquestion['content'], $oldquestion['format']), $oldquestion['tags']);
qa_post_index($oldquestion['postid'], 'Q', $oldquestion['postid'], $oldquestion['parentid'], $oldquestion['title'], $oldquestion['content'],
$oldquestion['format'], qa_viewer_text($oldquestion['content'], $oldquestion['format']), $oldquestion['tags'], $oldquestion['categoryid']);
foreach ($answers as $answer)
if ($answer['type']=='A') // even if question visible, don't index hidden or queued answers
qa_post_index($answer['postid'], $answer['type'], $oldquestion['postid'], $answer['parentid'], null,
$answer['content'], $answer['format'], qa_viewer_text($answer['content'], $answer['format']), null);
$answer['content'], $answer['format'], qa_viewer_text($answer['content'], $answer['format']), null, $answer['categoryid']);
foreach ($commentsfollows as $comment)
if ($comment['type']=='C') {
......@@ -247,12 +247,12 @@
if ( (!isset($answer)) || ($answer['type']=='A') ) // don't index comment if it or its parent is hidden
qa_post_index($comment['postid'], $comment['type'], $oldquestion['postid'], $comment['parentid'], null,
$comment['content'], $comment['format'], qa_viewer_text($comment['content'], $comment['format']), null);
$comment['content'], $comment['format'], qa_viewer_text($comment['content'], $comment['format']), null, $comment['categoryid']);
}
if ($closepost['parentid']==$oldquestion['postid'])
qa_post_index($closepost['postid'], $closepost['type'], $oldquestion['postid'], $closepost['parentid'], null,
$closepost['content'], $closepost['format'], qa_viewer_text($closepost['content'], $closepost['format']), null);
$closepost['content'], $closepost['format'], qa_viewer_text($closepost['content'], $closepost['format']), null, $closepost['categoryid']);
}
qa_report_event($wasqueued ? ($hidden ? 'q_reject' : 'q_approve') : ($hidden ? 'q_hide' : 'q_reshow'), $userid, $handle, $cookieid, array(
......@@ -314,6 +314,13 @@
qa_db_posts_set_category_path($otherpostids, $newpath);
$searchmodules=qa_load_modules_with('search', 'move_post');
foreach ($searchmodules as $searchmodule) {
$searchmodule->move_post($oldquestion['postid'], $categoryid);
foreach ($otherpostids as $otherpostid)
$searchmodule->move_post($otherpostid, $categoryid);
}
qa_report_event('q_move', $userid, $handle, $cookieid, array(
'postid' => $oldquestion['postid'],
'oldquestion' => $oldquestion,
......@@ -397,9 +404,9 @@
// Send through to any search modules for unindexing
$searches=qa_load_modules_with('search', 'unindex_post');
foreach ($searches as $search)
$search->unindex_post($postid);
$searchmodules=qa_load_modules_with('search', 'unindex_post');
foreach ($searchmodules as $searchmodule)
$searchmodule->unindex_post($postid);
}
......@@ -419,7 +426,7 @@
$contentchanged ? $userid : null, $contentchanged ? qa_remote_ip_address() : null);
if ( ($oldanswer['type']=='A') && ($question['type']=='Q') ) // don't index if question or answer are hidden/queued
qa_post_index($oldanswer['postid'], 'A', $question['postid'], $oldanswer['parentid'], null, $content, $format, $text, null);
qa_post_index($oldanswer['postid'], 'A', $question['postid'], $oldanswer['parentid'], null, $content, $format, $text, null, $oldanswer['categoryid']);
qa_report_event('a_edit', $userid, $handle, $cookieid, array(
'postid' => $oldanswer['postid'],
......@@ -467,13 +474,13 @@
qa_db_unupaqcount_update();
if (($question['type']=='Q') && !$hidden) { // even if answer visible, don't index if question is hidden or queued
qa_post_index($oldanswer['postid'], 'A', $question['postid'], $oldanswer['parentid'], null,
$oldanswer['content'], $oldanswer['format'], qa_viewer_text($oldanswer['content'], $oldanswer['format']), null);
qa_post_index($oldanswer['postid'], 'A', $question['postid'], $oldanswer['parentid'], null, $oldanswer['content'],
$oldanswer['format'], qa_viewer_text($oldanswer['content'], $oldanswer['format']), null, $oldanswer['categoryid']);
foreach ($commentsfollows as $comment)
if ( ($comment['type']=='C') && ($comment['parentid']==$oldanswer['postid']) ) // and don't index hidden/queued comments
qa_post_index($comment['postid'], $comment['type'], $question['postid'], $comment['parentid'], null,
$comment['content'], $comment['format'], qa_viewer_text($comment['content'], $comment['format']), null);
qa_post_index($comment['postid'], $comment['type'], $question['postid'], $comment['parentid'], null, $comment['content'],
$comment['format'], qa_viewer_text($comment['content'], $comment['format']), null, $comment['categoryid']);
}
qa_report_event($wasqueued ? ($hidden ? 'a_reject' : 'a_approve') : ($hidden ? 'a_hide' : 'a_reshow'), $userid, $handle, $cookieid, array(
......@@ -583,7 +590,7 @@
$contentchanged ? $userid : null, $contentchanged ? qa_remote_ip_address() : null);
if ( ($oldcomment['type']=='C') && ($question['type']=='Q') && (($parent['type']=='Q') || ($parent['type']=='A')) ) // all must be visible
qa_post_index($oldcomment['postid'], 'C', $question['postid'], $oldcomment['parentid'], null, $content, $format, $text, null);
qa_post_index($oldcomment['postid'], 'C', $question['postid'], $oldcomment['parentid'], null, $content, $format, $text, null, $oldcomment['categoryid']);
qa_report_event('c_edit', $userid, $handle, $cookieid, array(
'postid' => $oldcomment['postid'],
......@@ -636,7 +643,7 @@
qa_db_unupaqcount_update();
if ( ($oldanswer['type']=='A') && ($question['type']=='Q') && (($parent['type']=='Q') || ($parent['type']=='A')) ) // only if all fully visible
qa_post_index($oldanswer['postid'], 'C', $question['postid'], $parentid, null, $content, $format, $text, null);
qa_post_index($oldanswer['postid'], 'C', $question['postid'], $parentid, null, $content, $format, $text, null, $oldanswer['categoryid']);
qa_report_event('a_to_c', $userid, $handle, $cookieid, array(
'postid' => $oldanswer['postid'],
......@@ -680,8 +687,8 @@
qa_db_ccount_update();
if ( ($question['type']=='Q') && (($parent['type']=='Q') || ($parent['type']=='A')) && !$hidden) // only index if none of the things it depends on are hidden or queued
qa_post_index($oldcomment['postid'], 'C', $question['postid'], $oldcomment['parentid'], null,
$oldcomment['content'], $oldcomment['format'], qa_viewer_text($oldcomment['content'], $oldcomment['format']), null);
qa_post_index($oldcomment['postid'], 'C', $question['postid'], $oldcomment['parentid'], null, $oldcomment['content'],
$oldcomment['format'], qa_viewer_text($oldcomment['content'], $oldcomment['format']), null, $oldcomment['categoryid']);
qa_report_event($wasqueued ? ($hidden ? 'c_reject' : 'c_approve') : ($hidden ? 'c_hide' : 'c_reshow'), $userid, $handle, $cookieid, array(
'postid' => $oldcomment['postid'],
......
......@@ -27,8 +27,8 @@
/*
A full list of redundant (non-normal) information in the database that can be recalculated:
Recalculated in doreindexposts:
===============================
Recalculated in doreindexcontent:
================================
^titlewords (all): index of words in titles of posts
^contentwords (all): index of words in content of posts
^tagwords (all): index of words in tags of posts (a tag can contain multiple words)
......@@ -86,19 +86,50 @@
@list($operation, $length, $next, $done)=explode(',', $state);
switch ($operation) {
case 'doreindexposts':
qa_recalc_transition($state, 'doreindexposts_postcount');
case 'doreindexcontent':
qa_recalc_transition($state, 'doreindexcontent_pagereindex');
break;
case 'doreindexposts_postcount':
case 'doreindexcontent_pagereindex':
$pages=qa_db_pages_get_for_reindexing($next, 10);
if (count($pages)) {
require_once QA_INCLUDE_DIR.'qa-app-format.php';
$lastpageid=max(array_keys($pages));
foreach ($pages as $pageid => $page)
if (!($page['flags'] & QA_PAGE_FLAGS_EXTERNAL)) {
$searchmodules=qa_load_modules_with('search', 'unindex_page');
foreach ($searchmodules as $searchmodule)
$searchmodule->unindex_page($pageid);
$searchmodules=qa_load_modules_with('search', 'index_page');
if (count($searchmodules)) {
$indextext=qa_viewer_text($page['content'], 'html');
foreach ($searchmodules as $searchmodule)
$searchmodule->index_page($pageid, $page['tags'], $page['heading'], $page['content'], 'html', $indextext);
}
}
$next=1+$lastpageid;
$done+=count($pages);
$continue=true;
} else
qa_recalc_transition($state, 'doreindexcontent_postcount');
break;
case 'doreindexcontent_postcount':
qa_db_qcount_update();
qa_db_acount_update();
qa_db_ccount_update();
qa_recalc_transition($state, 'doreindexposts_reindex');
qa_recalc_transition($state, 'doreindexcontent_postreindex');
break;
case 'doreindexposts_reindex':
case 'doreindexcontent_postreindex':
$posts=qa_db_posts_get_for_reindexing($next, 10);
if (count($posts)) {
......@@ -109,9 +140,11 @@
qa_db_prepare_for_reindexing($next, $lastpostid);
qa_suspend_update_counts();
foreach ($posts as $postid => $post)
foreach ($posts as $postid => $post) {
qa_post_unindex($postid);
qa_post_index($postid, $post['type'], $post['questionid'], $post['parentid'], $post['title'], $post['content'],
$post['format'], qa_viewer_text($post['content'], $post['format']), $post['tags']);
$post['format'], qa_viewer_text($post['content'], $post['format']), $post['tags'], $post['categoryid']);
}
$next=1+$lastpostid;
$done+=count($posts);
......@@ -455,7 +488,11 @@
*/
{
switch ($operation) {
case 'doreindexposts_reindex':
case 'doreindexcontent_pagereindex':
$length=qa_db_count_pages();
break;
case 'doreindexcontent_postreindex':
$length=qa_opt('cache_qcount')+qa_opt('cache_acount')+qa_opt('cache_ccount');
break;
......@@ -514,14 +551,21 @@
$length=(int)$length;
switch ($operation) {
case 'doreindexposts_postcount':
case 'doreindexcontent_postcount':
case 'dorecountposts_postcount':
case 'dorecalccategories_postcount':
case 'dorefillevents_qcount':
$message=qa_lang('admin/recalc_posts_count');
break;
case 'doreindexposts_reindex':
case 'doreindexcontent_pagereindex':
$message=strtr(qa_lang('admin/reindex_pages_reindexed'), array(
'^1' => number_format($done),
'^2' => number_format($length)
));
break;
case 'doreindexcontent_postreindex':
$message=strtr(qa_lang('admin/reindex_posts_reindexed'), array(
'^1' => number_format($done),
'^2' => number_format($length)
......
......@@ -104,8 +104,11 @@
{
global $qa_cached_logged_in_points;
if (!isset($qa_cached_logged_in_points))
if (!isset($qa_cached_logged_in_points)) {
require_once QA_INCLUDE_DIR.'qa-db-selects.php';
$qa_cached_logged_in_points=qa_db_select_with_pending(qa_db_user_points_selectspec(qa_get_logged_in_userid(), true));
}
return $qa_cached_logged_in_points['points'];
}
......@@ -564,6 +567,63 @@
}
function qa_userids_to_handles($userids)
/*
Return an array mapping each userid in $userids to that user's handle (public username), or to null if not found
*/
{
if (QA_FINAL_EXTERNAL_USERS)
$rawuseridhandles=qa_get_public_from_userids($userids);
else {
require_once QA_INCLUDE_DIR.'qa-db-users.php';
$rawuseridhandles=qa_db_user_get_userid_handles($userids);
}
$gotuseridhandles=array();
foreach ($userids as $userid)
$gotuseridhandles[$userid]=@$rawuseridhandles[$userid];
return $gotuseridhandles;
}
function qa_handles_to_userids($handles, $exactonly=false)
/*
Return an array mapping each handle in $handles the user's userid, or null if not found. If $exactonly is true then
$handles must have the correct case and accents. Otherwise, handles are case- and accent-insensitive, and the keys
of the returned array will match the $handles provided, not necessary those in the DB.
*/
{
require_once QA_INCLUDE_DIR.'qa-util-string.php';
if (QA_FINAL_EXTERNAL_USERS)
$rawhandleuserids=qa_get_userids_from_public($handles);
else {
require_once QA_INCLUDE_DIR.'qa-db-users.php';
$rawhandleuserids=qa_db_user_get_handle_userids($handles);
}
$gothandleuserids=array();
if ($exactonly) { // only take the exact matches
foreach ($handles as $handle)
$gothandleuserids[$handle]=@$rawhandleuserids[$handle];
} else { // normalize to lowercase without accents, and then find matches
$normhandleuserids=array();
foreach ($rawhandleuserids as $handle => $userid)
$normhandleuserids[qa_string_remove_accents(qa_strtolower($handle))]=$userid;
foreach ($handles as $handle)
$gothandleuserids[$handle]=@$normhandleuserids[qa_string_remove_accents(qa_strtolower($handle))];
}
return $gothandleuserids;
}
function qa_user_permit_error($permitoption=null, $limitaction=null)
/*
Check whether the logged in user has permission to perform $permitoption. If $permitoption is null, this simply
......@@ -679,25 +739,21 @@
}
function qa_user_use_captcha($captchaoption)
function qa_user_use_captcha()
/*
Return whether a captcha should be presented to the current user for operation specified by $captchaoption
Return whether a captcha should be presented to the current user for writing posts
*/
{
if (qa_to_override(__FUNCTION__)) return qa_call_override(__FUNCTION__, $args=func_get_args());
$usecaptcha=false;
if (qa_opt($captchaoption)) {
if (qa_get_logged_in_level() < QA_USER_LEVEL_EXPERT) { // experts and above aren't shown captchas
$userid=qa_get_logged_in_userid();
if ( (!isset($userid)) || !(
QA_FINAL_EXTERNAL_USERS ||
(!qa_opt('captcha_on_unconfirmed')) || // we might not care about unconfirmed users
(!qa_opt('confirm_user_emails')) || // if this option off, we can't ask it of the user
(qa_get_logged_in_level()>=QA_USER_LEVEL_EXPERT) || // if assigned to a higher level, no need
(qa_get_logged_in_flags() & QA_USER_FLAGS_EMAIL_CONFIRMED) // actual confirmation
))
if (qa_opt('captcha_on_anon_post') && !isset($userid))
$usecaptcha=true;
elseif (qa_opt('confirm_user_emails') && qa_opt('captcha_on_unconfirmed') && !(qa_get_logged_in_flags() & QA_USER_FLAGS_EMAIL_CONFIRMED) )
$usecaptcha=true;
}
......@@ -718,20 +774,17 @@
$reason=false;
$maxpermitpost=max(qa_opt('permit_post_q'), qa_opt('permit_post_a'), qa_opt('permit_post_c')); // used to see which options are shown in admin
if (
(qa_opt('moderate_anon_post') || ($maxpermitpost <= QA_PERMIT_USERS)) && // no one is moderated if anons can post unmoderated
(qa_get_logged_in_level() < QA_USER_LEVEL_EXPERT) && // experts and above aren't moderated
qa_user_permit_error('permit_moderate') // if the user can approve posts, no point in moderating theirs
) {
$userid=qa_get_logged_in_userid();
if ( ($maxpermitpost > QA_PERMIT_USERS) && !isset($userid) )
if (qa_opt('moderate_anon_post') && !isset($userid))
$reason='login';
elseif ( ($maxpermitpost > QA_PERMIT_CONFIRMED) && qa_opt('confirm_user_emails') && qa_opt('moderate_unconfirmed') && !(qa_get_logged_in_flags() & QA_USER_FLAGS_EMAIL_CONFIRMED) )
elseif (qa_opt('confirm_user_emails') && qa_opt('moderate_unconfirmed') && !(qa_get_logged_in_flags() & QA_USER_FLAGS_EMAIL_CONFIRMED) )
$reason='confirm';
elseif ( ($maxpermitpost > QA_PERMIT_EXPERTS) && qa_opt('moderate_by_points') && (qa_get_logged_in_points() < qa_opt('moderate_points_limit') ))
elseif (qa_opt('moderate_by_points') && (qa_get_logged_in_points() < qa_opt('moderate_points_limit')))
$reason='points';
}
......
......@@ -25,8 +25,8 @@
*/
define('QA_VERSION', '1.5-beta-1'); // also used as suffix for .js and .css requests
define('QA_BUILD_DATE', '2011-12-14');
define('QA_VERSION', '1.5-beta-2'); // also used as suffix for .js and .css requests
define('QA_BUILD_DATE', '2012-01-04');
// Execution section of this file - remainder contains function definitions
......@@ -134,6 +134,13 @@
@define('QA_PERSISTENT_CONN_DB', false);
@define('QA_DEBUG_PERFORMANCE', false);
// Start performance monitoring
if (QA_DEBUG_PERFORMANCE) {
require_once 'qa-util-debug.php';
qa_usage_init();
}
// More for WordPress integration
if (defined('QA_FINAL_WORDPRESS_INTEGRATE_PATH')) {
......@@ -216,9 +223,15 @@
foreach ($pluginfiles as $pluginfile)
if (file_exists($pluginfile)) {
if (preg_match('/Plugin[ \t]*Minimum[ \t]*Question2Answer[ \t]*Version\:[ \t]*([0-9\.]+)\s/i', file_get_contents($pluginfile), $matches))
$contents=file_get_contents($pluginfile);
if (preg_match('/Plugin[ \t]*Minimum[ \t]*Question2Answer[ \t]*Version\:[ \t]*([0-9\.]+)\s/i', $contents, $matches))
if ( ((float)QA_VERSION>0) && ($matches[1]>(float)QA_VERSION) )
continue; // skip plugin which requires a later version
continue; // skip plugin which requires a later version of Q2A
if (preg_match('/Plugin[ \t]*Minimum[ \t]*PHP[ \t]*Version\:[ \t]*([0-9\.]+)\s/i', $contents, $matches))
if ( ((float)phpversion()>0) && ($matches[1]>(float)phpversion()) )
continue; // skip plugin which requires a later version of PHP
$qa_plugin_directory=dirname($pluginfile).'/';
$qa_plugin_urltoroot=substr($qa_plugin_directory, strlen(QA_BASE_DIR));
......@@ -362,7 +375,6 @@
// Function for registering varieties of Q2A modularity, which are (only) called from qa-plugin.php files
function qa_register_plugin_module($type, $include, $class, $name)
/*
Register a plugin module of $type named $name, whose class named $class is defined in file $include (or null if no include necessary)
This function relies on some global variable values and can only be called from a plugin's qa-plugin.php file
......@@ -399,7 +411,7 @@
global $qa_plugin_directory, $qa_plugin_urltoroot;
if (empty($qa_plugin_directory) || empty($qa_plugin_urltoroot))
qa_fatal_error('qa_register_plugin_layer() can only be called from a plugin qa-plugin.php file');
qa_fatal_error('qa_register_plugin_overrides() can only be called from a plugin qa-plugin.php file');
qa_register_overrides($include, $qa_plugin_directory, $qa_plugin_urltoroot);
}
......@@ -422,6 +434,9 @@
// Low-level functions used throughout Q2A
function qa_call($function, $args)
/*
Call $function with the arguments in the $args array (doesn't work with call-by-reference functions)
*/
{
switch (count($args)) { // call_user_func_array(...) is very slow, so we break out most cases
case 0: return $function();
......@@ -437,6 +452,10 @@
function qa_to_override($function)
/*
If $function has been overridden by a plugin override, return the name of the overriding function, otherwise return
null. But if the function is being called with the _base suffix, any override will be bypassed due to $qa_direct
*/
{
global $qa_overrides, $qa_direct;
......@@ -455,6 +474,9 @@
function qa_call_override($function, $args)
/*
Call the function which immediately overrides $function with the arguments in the $args array
*/
{
global $qa_overrides;
......@@ -469,6 +491,9 @@
function qa_exit($reason=null)
/*
Exit PHP immediately after reporting a shutdown with $reason to any installed process modules
*/
{
qa_report_process_stage('shutdown', $reason);
exit;
......@@ -778,7 +803,7 @@
function qa_remote_ip_address()
/*
Return the remote IP (v4) address of the user accessing the site, if it's available, or null otherwise
Return the remote IP address of the user accessing the site, if it's available, or null otherwise
*/
{
if (qa_to_override(__FUNCTION__)) return qa_call_override(__FUNCTION__, $args=func_get_args());
......
......@@ -52,8 +52,8 @@
return $substitutions;
}
echo '<font color="#c00"><code>Dark red = important to review.</code></font><br>';
echo '<font color="#c99"><code>Light red = probably safe to ignore.</code></font>';
echo '<font color="#cc0000"><code>Dark red = important to review.</code></font><br>';
echo '<font color="#cc9999"><code>Light red = probably safe to ignore.</code></font>';
echo '<H1>Checking US English files in <code>qa-include</code>...</H1>';
......@@ -207,7 +207,7 @@
function output_lang_issue($prefix, $key, $issue, $error=true)
{
echo '<font color="'.($error ? '#c00' : '#c99').'"><code>';
echo '<font color="'.($error ? '#cc0000' : '#cc9999').'"><code>';
echo 'qa-lang-<B>'.qa_html($prefix).'</B>.php:';
......
......@@ -768,7 +768,7 @@
case 5:
qa_db_upgrade_query('ALTER TABLE ^contentwords ADD COLUMN (type '.$definitions['contentwords']['type'].', questionid '.$definitions['contentwords']['questionid'].')');
qa_db_upgrade_query($locktablesquery);
$keyrecalc['doreindexposts']=true;
$keyrecalc['doreindexcontent']=true;
break;
// Up to here: Version 1.0 beta 2
......@@ -803,6 +803,7 @@
break;
case 10:
qa_db_upgrade_query('UNLOCK TABLES');
qa_db_upgrade_query(qa_db_create_table_sql('categories', array(
'categoryid' => $definitions['categories']['categoryid'],
'title' => $definitions['categories']['title'],
......@@ -825,6 +826,7 @@
break;
case 12:
qa_db_upgrade_query('UNLOCK TABLES');
qa_db_upgrade_query(qa_db_create_table_sql('pages', array(
'pageid' => $definitions['pages']['pageid'],
'title' => $definitions['pages']['title'],
......@@ -872,7 +874,7 @@
case 16:
qa_db_upgrade_table_columns($definitions, 'posts', array('format'));
qa_db_upgrade_query($locktablesquery);
$keyrecalc['doreindexposts']=true; // because of new treatment of apostrophes in words
$keyrecalc['doreindexcontent']=true; // because of new treatment of apostrophes in words
break;
case 17:
......@@ -891,6 +893,8 @@
// hard-code list of columns and indexes to ensure we ignore any added at a later stage
qa_db_upgrade_query('UNLOCK TABLES');
qa_db_upgrade_query(qa_db_create_table_sql('blobs', array(
'blobid' => $definitions['blobs']['blobid'],
'format' => $definitions['blobs']['format'],
......@@ -914,6 +918,8 @@
case 20:
if (!QA_FINAL_EXTERNAL_USERS) {
qa_db_upgrade_query('UNLOCK TABLES');
qa_db_upgrade_query(qa_db_create_table_sql('userlogins', array(
'userid' => $definitions['userlogins']['userid'],
'source' => $definitions['userlogins']['source'],
......@@ -933,6 +939,8 @@
case 21:
if (!QA_FINAL_EXTERNAL_USERS) {
qa_db_upgrade_query('UNLOCK TABLES');
qa_db_upgrade_query(qa_db_create_table_sql('userfields', array(
'fieldid' => $definitions['userfields']['fieldid'],
'title' => $definitions['userfields']['title'],
......@@ -961,6 +969,8 @@
// Up to here: Version 1.3 beta 2 and release
case 23:
qa_db_upgrade_query('UNLOCK TABLES');
qa_db_upgrade_query(qa_db_create_table_sql('widgets', array(
'widgetid' => $definitions['widgets']['widgetid'],
'place' => $definitions['widgets']['place'],
......@@ -976,6 +986,8 @@
break;
case 24:
qa_db_upgrade_query('UNLOCK TABLES');
qa_db_upgrade_query(qa_db_create_table_sql('tagwords', array(
'postid' => $definitions['tagwords']['postid'],
'wordid' => $definitions['tagwords']['wordid'],
......@@ -990,7 +1002,7 @@
qa_db_upgrade_query('ALTER TABLE ^words ADD COLUMN tagwordcount '.$definitions['words']['tagwordcount']);
qa_db_upgrade_query($locktablesquery);
$keyrecalc['doreindexposts']=true;
$keyrecalc['doreindexcontent']=true;
break;
// Up to here: Version 1.4 developer preview
......@@ -1084,6 +1096,8 @@
qa_db_upgrade_progress('Skipping messages table since it was already added by another Q2A site sharing these users.');
else {
qa_db_upgrade_query('UNLOCK TABLES');
qa_db_upgrade_query(qa_db_create_table_sql('messages', array(
'messageid' => $definitions['messages']['messageid'],
'fromuserid' => $definitions['messages']['fromuserid'],
......@@ -1102,6 +1116,8 @@
break;
case 35:
qa_db_upgrade_query('UNLOCK TABLES');
qa_db_upgrade_query(qa_db_create_table_sql('userfavorites', array(
'userid' => $definitions['userfavorites']['userid'],
'entitytype' => $definitions['userfavorites']['entitytype'],
......@@ -1118,6 +1134,8 @@
break;
case 36:
qa_db_upgrade_query('UNLOCK TABLES');
qa_db_upgrade_query(qa_db_create_table_sql('userevents', array(
'userid' => $definitions['userevents']['userid'],
'entitytype' => $definitions['userevents']['entitytype'],
......@@ -1139,6 +1157,8 @@
break;
case 37:
qa_db_upgrade_query('UNLOCK TABLES');
qa_db_upgrade_query(qa_db_create_table_sql('sharedevents', array(
'entitytype' => $definitions['sharedevents']['entitytype'],
'entityid' => $definitions['sharedevents']['entityid'],
......@@ -1178,6 +1198,8 @@
break;
case 42:
qa_db_upgrade_query('UNLOCK TABLES');
qa_db_upgrade_query(qa_db_create_table_sql('usermetas', array(
'userid' => $definitions['usermetas']['userid'],
'title' => $definitions['usermetas']['title'],
......@@ -1191,6 +1213,8 @@
break;
case 43:
qa_db_upgrade_query('UNLOCK TABLES');
qa_db_upgrade_query(qa_db_create_table_sql('postmetas', array(
'postid' => $definitions['postmetas']['postid'],
'title' => $definitions['postmetas']['title'],
......@@ -1204,6 +1228,8 @@
break;
case 44:
qa_db_upgrade_query('UNLOCK TABLES');
qa_db_upgrade_query(qa_db_create_table_sql('categorymetas', array(
'categoryid' => $definitions['categorymetas']['categoryid'],
'title' => $definitions['categorymetas']['title'],
......@@ -1217,6 +1243,8 @@
break;
case 45:
qa_db_upgrade_query('UNLOCK TABLES');
qa_db_upgrade_query(qa_db_create_table_sql('tagmetas', array(
'tag' => $definitions['tagmetas']['tag'],
'title' => $definitions['tagmetas']['title'],
......@@ -1236,6 +1264,8 @@
break;
case 47:
qa_db_upgrade_query('UNLOCK TABLES');
qa_db_upgrade_query(qa_db_create_table_sql('usernotices', array(
'noticeid' => $definitions['usernotices']['noticeid'],
'userid' => $definitions['usernotices']['userid'],
......
......@@ -30,115 +30,115 @@
}
function qa_db_usermeta_set($userid, $title, $content)
function qa_db_usermeta_set($userid, $key, $value)
/*
Set the metadata for user $userid with key $title to value $content
Set the metadata for user $userid with $key to $value. Keys beginning qa_ are reserved for the Q2A core.
*/
{
qa_db_meta_set('usermetas', 'userid', $userid, $title, $content);
qa_db_meta_set('usermetas', 'userid', $userid, $key, $value);
}
function qa_db_usermeta_clear($userid, $title)
function qa_db_usermeta_clear($userid, $key)
/*
Clear the metadata for user $userid with key $title ($title can also be an array of keys)
Clear the metadata for user $userid with $key ($key can also be an array of keys)
*/
{
qa_db_meta_clear('usermetas', 'userid', $userid, $title);
qa_db_meta_clear('usermetas', 'userid', $userid, $key);
}
function qa_db_usermeta_get($userid, $title)
function qa_db_usermeta_get($userid, $key)
/*
Return the metadata value for user $userid with key $title ($title can also be an array of keys in which case this
Return the metadata value for user $userid with $key ($key can also be an array of keys in which case this
returns an array of metadata key => value).
*/
{
return qa_db_meta_get('usermetas', 'userid', $userid, $title);
return qa_db_meta_get('usermetas', 'userid', $userid, $key);
}
function qa_db_postmeta_set($postid, $title, $content)
function qa_db_postmeta_set($postid, $key, $value)
/*
Set the metadata for post $postid with key $title to value $content
Set the metadata for post $postid with $key to $value. Keys beginning qa_ are reserved for the Q2A core.
*/
{
qa_db_meta_set('postmetas', 'postid', $postid, $title, $content);
qa_db_meta_set('postmetas', 'postid', $postid, $key, $value);
}
function qa_db_postmeta_clear($postid, $title)
function qa_db_postmeta_clear($postid, $key)
/*
Clear the metadata for post $postid with key $title ($title can also be an array of keys)
Clear the metadata for post $postid with $key ($key can also be an array of keys)
*/
{
qa_db_meta_clear('postmetas', 'postid', $postid, $title);
qa_db_meta_clear('postmetas', 'postid', $postid, $key);
}
function qa_db_postmeta_get($postid, $title)
function qa_db_postmeta_get($postid, $key)
/*
Return the metadata value for post $postid with key $title ($title can also be an array of keys in which case this
Return the metadata value for post $postid with $key ($key can also be an array of keys in which case this
returns an array of metadata key => value).
*/
{
return qa_db_meta_get('postmetas', 'postid', $postid, $title);
return qa_db_meta_get('postmetas', 'postid', $postid, $key);
}
function qa_db_categorymeta_set($categoryid, $title, $content)
function qa_db_categorymeta_set($categoryid, $key, $value)
/*
Set the metadata for category $categoryid with key $title to value $content
Set the metadata for category $categoryid with $key to $value. Keys beginning qa_ are reserved for the Q2A core.
*/
{
qa_db_meta_set('categorymetas', 'categoryid', $categoryid, $title, $content);
qa_db_meta_set('categorymetas', 'categoryid', $categoryid, $key, $value);
}
function qa_db_categorymeta_clear($categoryid, $title)
function qa_db_categorymeta_clear($categoryid, $key)
/*
Clear the metadata for category $categoryid with key $title ($title can also be an array of keys)
Clear the metadata for category $categoryid with $key ($key can also be an array of keys)
*/
{
qa_db_meta_clear('categorymetas', 'categoryid', $categoryid, $title);
qa_db_meta_clear('categorymetas', 'categoryid', $categoryid, $key);
}
function qa_db_categorymeta_get($categoryid, $title)
function qa_db_categorymeta_get($categoryid, $key)
/*
Return the metadata value for category $categoryid with key $title ($title can also be an array of keys in which
Return the metadata value for category $categoryid with $key ($key can also be an array of keys in which
case this returns an array of metadata key => value).
*/
{
return qa_db_meta_get('categorymetas', 'categoryid', $categoryid, $title);
return qa_db_meta_get('categorymetas', 'categoryid', $categoryid, $key);
}
function qa_db_tagmeta_set($tag, $title, $content)
function qa_db_tagmeta_set($tag, $key, $value)
/*
Set the metadata for tag $tag with key $title to value $content
Set the metadata for tag $tag with $key to $value. Keys beginning qa_ are reserved for the Q2A core.
*/
{
qa_db_meta_set('tagmetas', 'tag', $tag, $title, $content);
qa_db_meta_set('tagmetas', 'tag', $tag, $key, $value);
}
function qa_db_tagmeta_clear($tag, $title)
function qa_db_tagmeta_clear($tag, $key)
/*
Clear the metadata for tag $tag with key $title ($title can also be an array of keys)
Clear the metadata for tag $tag with $key ($key can also be an array of keys)
*/
{
qa_db_meta_clear('tagmetas', 'tag', $tag, $title);
qa_db_meta_clear('tagmetas', 'tag', $tag, $key);
}
function qa_db_tagmeta_get($tag, $title)
function qa_db_tagmeta_get($tag, $key)
/*
Return the metadata value for tag $tag with key $title ($title can also be an array of keys in which case this
Return the metadata value for tag $tag with $key ($key can also be an array of keys in which case this
returns an array of metadata key => value).
*/
{
return qa_db_meta_get('tagmetas', 'tag', $tag, $title);
return qa_db_meta_get('tagmetas', 'tag', $tag, $key);
}
......
......@@ -32,6 +32,31 @@
require_once QA_INCLUDE_DIR.'qa-db-post-create.php';
// For reindexing pages...
function qa_db_count_pages()
/*
Return the number of custom pages currently in the database
*/
{
return qa_db_read_one_value(qa_db_query_sub(
'SELECT COUNT(*) FROM ^pages'
));
}
function qa_db_pages_get_for_reindexing($startpageid, $count)
/*
Return the information to reindex up to $count pages starting from $startpageid in the database
*/
{
return qa_db_read_all_assoc(qa_db_query_sub(
'SELECT pageid, flags, tags, heading, content FROM ^pages WHERE pageid>=# ORDER BY pageid LIMIT #',
$startpageid, $count
), 'pageid');
}
// For reindexing posts...
function qa_db_posts_get_for_reindexing($startpostid, $count)
......@@ -40,7 +65,7 @@
*/
{
return qa_db_read_all_assoc(qa_db_query_sub(
"SELECT ^posts.postid, ^posts.title, ^posts.content, ^posts.format, ^posts.tags, ^posts.type, IF (^posts.type='Q', ^posts.postid, IF(parent.type='Q', parent.postid, grandparent.postid)) AS questionid, ^posts.parentid FROM ^posts LEFT JOIN ^posts AS parent ON ^posts.parentid=parent.postid LEFT JOIN ^posts as grandparent ON parent.parentid=grandparent.postid WHERE ^posts.postid>=# AND ( (^posts.type='Q') OR (^posts.type='A' AND parent.type<=>'Q') OR (^posts.type='C' AND parent.type<=>'Q') OR (^posts.type='C' AND parent.type<=>'A' AND grandparent.type<=>'Q') ) ORDER BY postid LIMIT #",
"SELECT ^posts.postid, ^posts.title, ^posts.content, ^posts.format, ^posts.tags, ^posts.categoryid, ^posts.type, IF (^posts.type='Q', ^posts.postid, IF(parent.type='Q', parent.postid, grandparent.postid)) AS questionid, ^posts.parentid FROM ^posts LEFT JOIN ^posts AS parent ON ^posts.parentid=parent.postid LEFT JOIN ^posts as grandparent ON parent.parentid=grandparent.postid WHERE ^posts.postid>=# AND ( (^posts.type='Q') OR (^posts.type='A' AND parent.type<=>'Q') OR (^posts.type='C' AND parent.type<=>'Q') OR (^posts.type='C' AND parent.type<=>'A' AND grandparent.type<=>'Q') ) ORDER BY postid LIMIT #",
$startpostid, $count
), 'postid');
}
......
......@@ -775,13 +775,12 @@
if (strlen($handle)) { // to allow searching for multi-word usernames (only works if search query contains full username and nothing else)
if (QA_FINAL_EXTERNAL_USERS) {
$userids=qa_get_userids_from_public(array($handle));
$userid=@$userids[$handle];
if (strlen($userid)) {
if (count($userids)) {
$selectspec['source'].=($selectparts++ ? " UNION ALL " : "").
"(SELECT postid AS questionid, LOG(#/qposts) AS score, 'Q' AS matchposttype, postid AS matchpostid FROM ^posts JOIN ^userpoints ON ^posts.userid=^userpoints.userid WHERE ^posts.userid=$ AND type='Q')";
array_push($selectspec['arguments'], QA_IGNORED_WORDS_FREQ, $userid);
array_push($selectspec['arguments'], QA_IGNORED_WORDS_FREQ, reset($userids));
}
} else {
......@@ -931,7 +930,8 @@
*/
{
$selectspec=array(
'columns' => array('pageid', 'title', 'flags', 'permit', 'nav', 'tags', 'position', 'heading'),
'columns' => array('pageid', 'title', 'flags', 'permit' => 'permit+0', 'nav', 'tags', 'position', 'heading'),
// +0 required to work around MySQL bug where by permit value is mis-read as signed, e.g. -106 instead of 150
'arraykey' => 'pageid',
'sortasc' => 'position',
);
......
......@@ -106,6 +106,36 @@
));
}
function qa_db_user_get_userid_handles($userids)
/*
Return an array mapping mapping each userid in $userids that can be found to that user's handle
*/
{
if (count($userids))
return qa_db_read_all_assoc(qa_db_query_sub(
'SELECT userid, handle FROM ^users WHERE userid IN (#)',
$userids
), 'userid', 'handle');
else
return array();
}
function qa_db_user_get_handle_userids($handles)
/*
Return an array mapping mapping each handle in $handle that can be found to that user's userid
*/
{
if (count($handles))
return qa_db_read_all_assoc(qa_db_query_sub(
'SELECT handle, userid FROM ^users WHERE handle IN ($)',
$handles
), 'handle', 'userid');
else
return array();
}
function qa_db_user_set($userid, $field, $value)
/*
......
......@@ -30,14 +30,6 @@
define('QA_BASE_DIR', dirname(empty($_SERVER['SCRIPT_FILENAME']) ? dirname(__FILE__) : $_SERVER['SCRIPT_FILENAME']).'/');
// Start performance monitoring
if (QA_DEBUG_PERFORMANCE) {
require_once 'qa-util-debug.php';
qa_usage_init();
}
// If this is an special non-page request, branch off here
if (@$_POST['qa']=='ajax')
......
......@@ -203,12 +203,14 @@
'refill_events_note' => ' - for each user\'s list of updates',
'refill_events_refilled' => 'Refilled for ^1 of ^2 questions...',
'refill_events' => 'Refill event streams',
'reindex_content' => 'Reindex content',
'reindex_content_note' => ' - for searching and related question suggestions',
'reindex_content_stop' => 'Stop reindexing',
'reindex_pages_reindexed' => 'Reindexed ^1 of ^2 pages...',
'reindex_posts_complete' => 'All posts were successfully reindexed.',
'reindex_posts_note' => ' - for searching and related question suggestions',
'reindex_posts_reindexed' => 'Reindexed ^1 of ^2 posts...',
'reindex_posts_stop' => 'Stop reindexing',
'reindex_posts_wordcounted' => 'Recounted ^1 of ^2 words...',
'reindex_posts' => 'Reindex posts',
'requires_php_version' => 'Disabled - requires PHP ^ or later',
'requires_q2a_version' => 'Disabled - requires Question2Answer ^ or later',
'reset_options_button' => 'Reset to Defaults',
'resume_mailing_button' => 'Resume Mailing',
......
......@@ -34,7 +34,7 @@
'a_notify_label' => 'Email me if my answer is selected or commented on',
'a_notify_x_label' => 'Email me (^) if my answer is selected or commented on',
'a_waiting_your_approval' => 'This answer is waiting for your approval',
'a_your_waiting_approval' => 'Your answer is waiting for approval',
'a_your_waiting_approval' => 'Your answer will be checked and approved shortly.',
'add_answer_button' => 'Add answer',
'add_comment_button' => 'Add comment',
'add_q_favorites' => 'Add this question to my favorites',
......@@ -56,7 +56,7 @@
'c_notify_label' => 'Email me if a comment is added after mine',
'c_notify_x_label' => 'Email me (^) if a comment is added after mine',
'c_waiting_your_approval' => 'This comment is waiting for your approval',
'c_your_waiting_approval' => 'Your comment is waiting for approval',
'c_your_waiting_approval' => 'Your comment will be checked and approved shortly.',
'category_js_note' => 'To select any category, please enable Javascript in your web browser.',
'category_required' => 'Please choose a category',
'claim_button' => 'I wrote this',
......@@ -130,7 +130,7 @@
'q_title_label' => 'The question in one sentence:',
'q_waiting_approval' => 'This question is waiting for approval',
'q_waiting_your_approval' => 'This question is waiting for your approval',
'q_your_waiting_approval' => 'Your question is waiting for approval',
'q_your_waiting_approval' => 'Your question will be checked and approved shortly.',
'recat_button' => 'recategorize',
'recat_popup' => 'Change this question\'s category',
'recat_q_title' => 'Recategorize question',
......
......@@ -501,7 +501,9 @@
if (!QA_FINAL_EXTERNAL_USERS)
array_push($showoptions, 'confirm_user_emails', 'confirm_user_required', 'suspend_register_users', '');
$maxpermitpost=max($getoptions['permit_post_q'], $getoptions['permit_post_a'], $getoptions['permit_post_c']);
$maxpermitpost=max($getoptions['permit_post_q'], $getoptions['permit_post_a']);
if (qa_opt('comment_on_qs') || qa_opt('comment_on_as'))
$maxpermitpost=max($maxpermitpost, $getoptions['permit_post_c']);
$captchamodules=qa_list_modules('captcha');
......@@ -534,51 +536,42 @@
array_push($showoptions, 'flagging_of_posts', 'flagging_notify_first', 'flagging_notify_every', 'flagging_hide_after', '');
$checkboxtodisplay=array(
'confirm_user_required' => 'option_confirm_user_emails',
'flagging_hide_after' => 'option_flagging_of_posts',
'flagging_notify_every' => 'option_flagging_of_posts',
'flagging_notify_first' => 'option_flagging_of_posts',
'max_rate_ip_flags' => 'option_flagging_of_posts',
'max_rate_user_flags' => 'option_flagging_of_posts',
);
array_push($showoptions, 'block_ips_write', '');
if (!QA_FINAL_EXTERNAL_USERS)
array_push($showoptions, 'max_rate_ip_registers', 'max_rate_ip_logins', '');
array_push($showoptions,
'max_rate_ip_qs', 'max_rate_user_qs', 'max_rate_ip_as', 'max_rate_user_as', 'max_rate_ip_cs', 'max_rate_user_cs', '',
'max_rate_ip_votes', 'max_rate_user_votes', 'max_rate_ip_flags', 'max_rate_user_flags', 'max_rate_ip_uploads', 'max_rate_user_uploads'
);
array_push($showoptions, 'max_rate_ip_qs', 'max_rate_user_qs', 'max_rate_ip_as', 'max_rate_user_as');
if (qa_opt('comment_on_qs') || qa_opt('command_on_as'))
array_push($showoptions, 'max_rate_ip_cs', 'max_rate_user_cs');
if (qa_opt('allow_private_messages')) {
$showoptions[]='max_rate_ip_messages';
$showoptions[]='max_rate_user_messages';
}
$showoptions[]='';
if (qa_opt('voting_on_qs') || qa_opt('voting_on_as'))
array_push($showoptions, 'max_rate_ip_votes', 'max_rate_user_votes');
array_push($showoptions, 'max_rate_ip_flags', 'max_rate_user_flags', 'max_rate_ip_uploads', 'max_rate_user_uploads');
if (qa_opt('allow_private_messages'))
array_push($showoptions, 'max_rate_ip_messages', 'max_rate_user_messages');
$formstyle='wide';
if ($maxpermitpost > QA_PERMIT_USERS)
$checkboxtodisplay=array_merge($checkboxtodisplay, array(
'captcha_on_unconfirmed' => 'option_confirm_user_emails && option_captcha_on_anon_post',
'captcha_module' => 'option_captcha_on_register || option_captcha_on_anon_post || option_captcha_on_reset_password || option_captcha_on_feedback',
'moderate_unconfirmed' => 'option_confirm_user_emails && option_moderate_anon_post',
'moderate_by_points' => 'option_moderate_anon_post',
'moderate_points_limit' => 'option_moderate_anon_post && option_moderate_by_points',
'moderate_points_label_off' => 'option_moderate_anon_post && !option_moderate_by_points',
'moderate_points_label_on' => 'option_moderate_anon_post && option_moderate_by_points',
));
else
$checkboxtodisplay=array_merge($checkboxtodisplay, array(
'captcha_on_unconfirmed' => 'option_confirm_user_emails',
'captcha_module' => 'option_captcha_on_register || option_captcha_on_unconfirmed || option_captcha_on_reset_password || option_captcha_on_feedback',
'moderate_unconfirmed' => 'option_confirm_user_emails',
'moderate_points_limit' => 'option_moderate_by_points',
'moderate_points_label_off' => '!option_moderate_by_points',
'moderate_points_label_on' => 'option_moderate_by_points',
));
$checkboxtodisplay=array(
'confirm_user_required' => 'option_confirm_user_emails',
'captcha_on_unconfirmed' => 'option_confirm_user_emails',
'captcha_module' => 'option_captcha_on_register || option_captcha_on_anon_post || (option_confirm_user_emails && option_captcha_on_unconfirmed) || option_captcha_on_reset_password || option_captcha_on_feedback',
'moderate_unconfirmed' => 'option_confirm_user_emails',
'moderate_points_limit' => 'option_moderate_by_points',
'moderate_points_label_off' => '!option_moderate_by_points',
'moderate_points_label_on' => 'option_moderate_by_points',
'flagging_hide_after' => 'option_flagging_of_posts',
'flagging_notify_every' => 'option_flagging_of_posts',
'flagging_notify_first' => 'option_flagging_of_posts',
'max_rate_ip_flags' => 'option_flagging_of_posts',
'max_rate_user_flags' => 'option_flagging_of_posts',
);
break;
case 'mailing':
......
......@@ -222,13 +222,13 @@
else {
$setheading=isset($errors['heading']) ? $editpage['heading'] : $inheading;
$setslug=isset($errors['slug']) ? $editpage['tags'] : $inslug;
$setcontent=isset($errors['content']) ? $editpage['content'] : $incontent;
qa_db_page_set_fields($editpage['pageid'],
isset($errors['name']) ? $editpage['title'] : $inname,
0,
isset($errors['slug']) ? $editpage['tags'] : $inslug,
$setheading, $setcontent, $inpermit);
$setslug, $setheading, $setcontent, $inpermit);
$searchmodules=qa_load_modules_with('search', 'unindex_page');
foreach ($searchmodules as $searchmodule)
......@@ -238,7 +238,7 @@
$searchmodules=qa_load_modules_with('search', 'index_page');
foreach ($searchmodules as $searchmodule)
$searchmodule->index_page($editpage['pageid'], $setheading, $setcontent, 'html', $indextext);
$searchmodule->index_page($editpage['pageid'], $setslug, $setheading, $setcontent, 'html', $indextext);
}
qa_db_page_move($editpage['pageid'], substr($inposition, 0, 1), substr($inposition, 1));
......@@ -261,7 +261,7 @@
$searchmodules=qa_load_modules_with('search', 'index_page');
foreach ($searchmodules as $searchmodule)
$searchmodule->index_page($pageid, $inheading, $incontent, 'html', $indextext);
$searchmodule->index_page($pageid, $inslug, $inheading, $incontent, 'html', $indextext);
}
qa_db_page_move($pageid, substr($inposition, 0, 1), substr($inposition, 1));
......
......@@ -99,6 +99,7 @@
'author_uri' => 'Plugin Author URI',
'license' => 'Plugin License',
'min_q2a' => 'Plugin Minimum Question2Answer Version',
'min_php' => 'Plugin Minimum PHP Version',
'update' => 'Plugin Update Check URI',
));
......@@ -153,6 +154,10 @@
if (is_numeric(@$metadata['min_q2a']) && ((float)QA_VERSION>0) && $metadata['min_q2a']>(float)QA_VERSION)
$pluginhtml='<STRIKE STYLE="color:#999">'.$pluginhtml.'</STRIKE><BR><SPAN STYLE="color:#f00">'.
qa_lang_html_sub('admin/requires_q2a_version', qa_html($metadata['min_q2a'])).'</SPAN>';
elseif (is_numeric(@$metadata['min_php']) && ((float)phpversion()>0) && $metadata['min_php']>(float)phpversion())
$pluginhtml='<STRIKE STYLE="color:#999">'.$pluginhtml.'</STRIKE><BR><SPAN STYLE="color:#f00">'.
qa_lang_html_sub('admin/requires_php_version', qa_html($metadata['min_php'])).'</SPAN>';
$qa_content['form']['fields'][]=array(
'type' => 'custom',
......
......@@ -43,7 +43,7 @@
$allowstates=array(
'dorecountposts',
'doreindexposts',
'doreindexcontent',
'dorecalcpoints',
'dorefillevents',
'dorecalccategories',
......
......@@ -215,10 +215,10 @@
'note' => '<SPAN ID="recount_posts_note">'.qa_lang_html('admin/recount_posts_note').'</SPAN>',
),
'reindex_posts' => array(
'label' => qa_lang_html('admin/reindex_posts'),
'tags' => 'NAME="doreindexposts" onClick="return qa_recalc_click(this.name, this, '.qa_js(qa_lang('admin/reindex_posts_stop')).', \'reindex_posts_note\');"',
'note' => '<SPAN ID="reindex_posts_note">'.qa_lang_html('admin/reindex_posts_note').'</SPAN>',
'reindex_content' => array(
'label' => qa_lang_html('admin/reindex_content'),
'tags' => 'NAME="doreindexcontent" onClick="return qa_recalc_click(this.name, this, '.qa_js(qa_lang('admin/reindex_content_stop')).', \'reindex_content_note\');"',
'note' => '<SPAN ID="reindex_content_note">'.qa_lang_html('admin/reindex_content_note').'</SPAN>',
),
'recalc_points' => array(
......
......@@ -93,6 +93,8 @@
'login' => 'users/login_title',
'register' => 'users/register_title',
'account' => 'profile/my_account_title',
'favorites' => 'misc/my_favorites_title',
'updates' => 'misc/recent_updates_title',
'ip' => 'admin/ip_address_pages',
'admin' => 'admin/admin_title',
......
......@@ -90,7 +90,7 @@
// Process input
$usecaptcha=qa_user_use_captcha('captcha_on_anon_post');
$usecaptcha=qa_user_use_captcha();
$in['title']=qa_post_text('title'); // allow title and tags to be posted by an external form
$in['extra']=qa_opt('extra_field_active') ? qa_post_text('extra') : null;
......@@ -109,8 +109,11 @@
$errors=array();
$filtermodules=qa_load_modules_with('filter', 'filter_question');
foreach ($filtermodules as $filtermodule)
foreach ($filtermodules as $filtermodule) {
$oldin=$in;
$filtermodule->filter_question($in, $errors, null);
qa_update_post_text($in, $oldin);
}
if (qa_using_categories() && count($categories) && (!qa_opt('allow_no_category')) && !isset($in['categoryid']))
$errors['categoryid']=qa_lang_html('question/category_required'); // check this here because we need to know count($categories)
......@@ -175,6 +178,7 @@
'buttons' => array(
'ask' => array(
'tags' => method_exists($editor, 'update_script') ? ('onClick="'.$editor->update_script('content').'"') : '',
'label' => qa_lang_html('question/ask_button'),
),
),
......
......@@ -43,7 +43,7 @@
qa_db_user_profile_selectspec($userid, true)
);
$usecaptcha=qa_user_use_captcha('captcha_on_feedback');
$usecaptcha=qa_opt('captcha_on_feedback') && qa_user_use_captcha();
// Check feedback is enabled
......
......@@ -74,6 +74,11 @@
if (qa_clicked('doblock')) {
$oldblocked=qa_opt('block_ips_write');
qa_set_option('block_ips_write', (strlen($oldblocked) ? ($oldblocked.' , ') : '').$ip);
qa_report_event('ip_block', $userid, qa_get_logged_in_handle(), qa_cookie_get(), array(
'ip' => $ip,
));
qa_redirect(qa_request());
}
......@@ -87,6 +92,11 @@
unset($blockipclauses[$key]);
qa_set_option('block_ips_write', implode(' , ', $blockipclauses));
qa_report_event('ip_unblock', $userid, qa_get_logged_in_handle(), qa_cookie_get(), array(
'ip' => $ip,
));
qa_redirect(qa_request());
}
......
......@@ -359,6 +359,8 @@
$form['fields']['content']=array_merge($form['fields']['content'],
qa_editor_load_field($editor, $qa_content, $content, $format, 'q_content', 12, true));
$form['buttons']['save']['tags']=method_exists($editor, 'update_script') ? ('onClick="'.$editor->update_script('q_content').'"') : '';
$form['hidden']['q_editor']=qa_html($editorname);
} else
......@@ -420,8 +422,13 @@
$errors=array();
$filtermodules=qa_load_modules_with('filter', 'filter_question');
foreach ($filtermodules as $filtermodule)
foreach ($filtermodules as $filtermodule) {
$oldin=$in;
$filtermodule->filter_question($in, $errors, $question);
if ($question['editable'])
qa_update_post_text($in, $oldin);
}
if (empty($errors)) {
$userid=qa_get_logged_in_userid();
......@@ -445,14 +452,14 @@
if (!isset($in['categoryid']))
$in['categoryid']=$question['categoryid'];
if (qa_using_categories() && strcmp($in['categoryid'], $question['categoryid']))
qa_question_set_category($question, $in['categoryid'], $userid, $handle, $cookieid, $answers, $commentsfollows, $closepost);
$setnotify=$question['isbyuser'] ? qa_combine_notify_email($question['userid'], $in['notify'], $in['email']) : $question['notify'];
qa_question_set_content($question, $in['title'], $in['content'], $in['format'], $in['text'],
qa_tags_to_tagstring($in['tags']), $setnotify, $userid, $handle, $cookieid, $in['extra']);
if (qa_using_categories() && strcmp($in['categoryid'], $question['categoryid']))
qa_question_set_category($question, $in['categoryid'], $userid, $handle, $cookieid, $answers, $commentsfollows, $closepost);
return true;
}
......@@ -611,6 +618,7 @@
'buttons' => array(
'save' => array(
'tags' => method_exists($editor, 'update_script') ? ('onClick="'.$editor->update_script($prefix.'content').'"') : '',
'label' => qa_lang_html('main/save_button'),
),
......@@ -707,8 +715,11 @@
$errors=array();
$filtermodules=qa_load_modules_with('filter', 'filter_answer');
foreach ($filtermodules as $filtermodule)
foreach ($filtermodules as $filtermodule) {
$oldin=$in;
$filtermodule->filter_answer($in, $errors, $question, $answer);
qa_update_post_text($in, $oldin);
}
if (empty($errors)) {
$userid=qa_get_logged_in_userid();
......@@ -822,6 +833,7 @@
'buttons' => array(
'save' => array(
'tags' => method_exists($editor, 'update_script') ? ('onClick="'.$editor->update_script($prefix.'content').'"') : '',
'label' => qa_lang_html('main/save_button'),
),
......@@ -866,8 +878,11 @@
$errors=array();
$filtermodules=qa_load_modules_with('filter', 'filter_comment');
foreach ($filtermodules as $filtermodule)
foreach ($filtermodules as $filtermodule) {
$oldin=$in;
$filtermodule->filter_comment($in, $errors, $question, $parent, $comment);
qa_update_post_text($in, $oldin);
}
if (empty($errors)) {
$userid=qa_get_logged_in_userid();
......
......@@ -273,8 +273,11 @@
$errors=array();
$filtermodules=qa_load_modules_with('filter', 'filter_answer');
foreach ($filtermodules as $filtermodule)
foreach ($filtermodules as $filtermodule) {
$oldin=$in;
$filtermodule->filter_answer($in, $errors, $question, null);
qa_update_post_text($in, $oldin);
}
if ($usecaptcha)
qa_captcha_validate_post($errors);
......@@ -326,8 +329,11 @@
$errors=array();
$filtermodules=qa_load_modules_with('filter', 'filter_comment');
foreach ($filtermodules as $filtermodule)
foreach ($filtermodules as $filtermodule) {
$oldin=$in;
$filtermodule->filter_comment($in, $errors, $question, $parent, null);
qa_update_post_text($in, $oldin);
}
if ($usecaptcha)
qa_captcha_validate_post($errors);
......
......@@ -81,7 +81,7 @@
}
}
$usecaptcha=qa_user_use_captcha('captcha_on_anon_post');
$usecaptcha=qa_user_use_captcha();
// Deal with question not found or not viewable, otherwise report the view event
......
......@@ -43,11 +43,11 @@
if (QA_FINAL_EXTERNAL_USERS) {
$publictouserid=qa_get_userids_from_public(array($handle));
$userid=@$publictouserid[$handle];
if (!isset($userid))
if (!count($publictouserid))
return include QA_INCLUDE_DIR.'qa-page-not-found.php';
$userid=reset($publictouserid); // don't use $publictouserid[$handle] since $handle capitalization might be different
$usershtml=qa_get_users_html(array($userid), false, qa_path_to_root(), true);
$userhtml=@$usershtml[$userid];
......
......@@ -222,10 +222,15 @@
// Set appropriate selected flags for navigation (not done in qa_content_prepare() since it also applies to sub-navigation)
$selfpathhtml=qa_path_html($requestlower);
foreach ($qa_content['navigation'] as $navtype => $navigation)
if (is_array($navigation) && ($navtype!='cat'))
foreach ($navigation as $navprefix => $navlink)
if (substr($requestlower.'$', 0, strlen($navprefix)) == $navprefix)
if (
(substr($requestlower.'$', 0, strlen($navprefix)) == $navprefix) ||
(strtolower(@$navlink['url'])==$selfpathhtml) // this check is needed for custom links that go to Q2A pages
)
$qa_content['navigation'][$navtype][$navprefix]['selected']=true;
// Slide down notifications
......@@ -664,12 +669,17 @@
$qa_content['notices'][]=qa_notice_form($notice['noticeid'], qa_viewer_html($notice['content'], $notice['format']), $notice);
} else {
require_once QA_INCLUDE_DIR.'qa-util-string.php';
$loginmodules=qa_load_modules_with('login', 'login_html');
foreach ($loginmodules as $tryname => $module) {
ob_start();
$module->login_html(isset($topath) ? (qa_opt('site_url').$topath) : qa_path($request, $_GET, qa_opt('site_url')), 'menu');
$qa_content['navigation']['user'][$tryname]=array('label' => ob_get_clean());
$label=ob_get_clean();
if (strlen($label))
$qa_content['navigation']['user'][implode('-', qa_string_to_words($tryname))]=array('label' => $label);
}
if (!empty($userlinks['login']))
......
......@@ -32,7 +32,7 @@
class qa_search_basic {
function index_post($postid, $type, $questionid, $parentid, $title, $content, $format, $text, $tagstring)
function index_post($postid, $type, $questionid, $parentid, $title, $content, $format, $text, $tagstring, $categoryid)
{
require_once QA_INCLUDE_DIR.'qa-db-post-create.php';
......@@ -104,7 +104,13 @@
}
function index_page($pageid, $title, $content, $format, $text)
function move_post($postid, $categoryid)
{
// for now, the built-in search engine ignores categories
}
function index_page($pageid, $request, $title, $content, $format, $text)
{
// for now, the built-in search engine ignores custom pages
}
......
......@@ -615,15 +615,15 @@
$this->output('<H1>');
if (isset($title))
$this->output($title);
if (isset($favorite)) {
$this->output('<DIV CLASS="qa-favoriting" '.@$favorite['favorite_tags'].'>');
$this->favorite_inner_html($favorite);
$this->output('</DIV>');
}
if (isset($title))
$this->output($title);
if (isset($this->content['error'])) {
$this->output('</H1>');
$this->error(@$this->content['error']);
......
......@@ -94,7 +94,7 @@
);
$options=qa_post_html_defaults('Q');
$usershtml=qa_userids_handles_html(qa_userids_handles_html($questions));
$usershtml=qa_userids_handles_html($questions);
foreach ($questions as $question)
$q_list['qs'][]=qa_post_html_fields($question, $userid, $cookieid, $usershtml, null, $options);
......
......@@ -141,11 +141,11 @@
status : true,
cookie : true,
xfbml : true,
oauth : true,
oauth : true
});
FB.Event.subscribe('<?php echo $logout ? 'auth.logout' : 'auth.login'?>', function(response) {
window.location=<?php echo qa_js($tourl)?>;
setTimeout("window.location=<?php echo qa_js($tourl)?>", 100);
});
};
(function(d){
......
......@@ -34,6 +34,7 @@
Plugin Author URI: http://www.question2answer.org/
Plugin License: GPLv2
Plugin Minimum Question2Answer Version: 1.3
Plugin Minimum PHP Version: 5
Plugin Update Check URI:
*/
......
......@@ -62,7 +62,7 @@ p {margin-top:0;}
h1 {margin:1em 0 0.5em 0; color:#c659ab; font-size:28px; font-weight:bold;}
h2 {font-size:22px; color:#c659ab; padding-top:12px; clear:both;}
.qa-favoriting {float:right; margin-right:16px;}
.qa-favoriting {float:right; padding-right:16px;}
.qa-favorite-button,.qa-favorite-hover,.qa-unfavorite-button,.qa-unfavorite-hover {background:url(favorite-heart.png) no-repeat; border:0; height:49px; width:50px;}
.qa-favorite-button {background-position: 0 -49px;}
......@@ -447,6 +447,9 @@ h2 {font-size:22px; color:#c659ab; padding-top:12px; clear:both;}
.qa-favorite-image {background:url(favorite-heart.png) no-repeat; background-position: 0 0px; border:0; height:49px; width:50px; vertical-align:middle; display:inline-block;}
/* IE6 friendly versions of icons with binary alpha channel */
* html .qa-favorite-button {background:url(favorite-heart-ie6.png) no-repeat 0 -49px;}
* html .qa-favorite-hover,* html .qa-unfavorite-hover {background:url(favorite-heart-ie6.png) no-repeat 0 0px;}
* html .qa-unfavorite-button {background:url(favorite-heart-ie6.png) no-repeat 0 -98px;}
* html .qa-form-light-button-edit,* html .qa-form-light-hover-edit,* html .qa-form-light-button-retagcat,* html .qa-form-light-hover-retagcat
{background:url(edit-icon-ie6.png) no-repeat left center;}
* html .qa-form-light-button-flag,* html .qa-form-light-hover-flag {background:url(flag-icon-ie6.png) no-repeat left center;}
......@@ -459,6 +462,10 @@ h2 {font-size:22px; color:#c659ab; padding-top:12px; clear:both;}
* html .qa-form-light-button-reshow,* html .qa-form-light-hover-reshow {background:url(reshow-icon-ie6.png) no-repeat left center;}
* html .qa-form-light-button-claim,* html .qa-form-light-hover-claim {background:url(claim-icon-ie6.png) no-repeat left center;}
* html .qa-form-light-button-delete,* html .qa-form-light-hover-delete {background:url(delete-icon-ie6.png) no-repeat left center;}
* html .qa-form-light-button-approve,* html .qa-form-light-hover-approve {background:url(approve-icon-ie6.png) no-repeat left center;}
* html .qa-form-light-button-reject,* html .qa-form-light-hover-reject {background:url(reject-icon-ie6.png) no-repeat left center;}
* html .qa-form-light-button-close,* html .qa-form-light-hover-close {background:url(close-icon-ie6.png) no-repeat left center;}
* html .qa-form-light-button-reopen,* html .qa-form-light-hover-reopen {background:url(reopen-icon-ie6.png) no-repeat left center;}
* html .qa-vote-up-button {background:url(vote-buttons-ie6.png) no-repeat 0 0;}
* html .qa-vote-up-hover {background:url(vote-buttons-ie6.png) no-repeat 0 -29px;}
* html .qa-vote-up-disabled {background:url(vote-buttons-ie6.png) no-repeat 0 -116px;}
......@@ -470,4 +477,5 @@ h2 {font-size:22px; color:#c659ab; padding-top:12px; clear:both;}
* html .qa-voted-down-button {background:url(vote-buttons-ie6.png) no-repeat -27px -87px;}
* html .qa-voted-down-hover {background:url(vote-buttons-ie6.png) no-repeat -27px -29px;}
* html .qa-tag-link {background:url(tag-icon-ie6.png) no-repeat left center;}
* html .qa-a-count {background:url(a-count-icon-ie6.png) no-repeat 32px 13px;}
\ No newline at end of file
* html .qa-a-count {background:url(a-count-icon-ie6.png) no-repeat 32px 13px;}
* html .qa-favorite-image {background:url(favorite-heart-ie6.png) no-repeat 0 0px;}
......@@ -62,9 +62,9 @@ p {margin-top:0;}
h1 {font-size:22px; margin:22px 0;}
h2 {font-size:16px; padding-top:12px; clear:both;}
.qa-favoriting {float:right; margin-right:48px; margin-top:4px;}
.qa-favoriting {float:right; padding-right:48px; padding-top:4px;}
.qa-favorite-button,.qa-favorite-hover,.qa-unfavorite-button,.qa-unfavorite-hover {background:url(favorite-plus.png) no-repeat; border:0; height:26px; width:26px;}
.qa-favorite-button,.qa-favorite-hover,.qa-unfavorite-button,.qa-unfavorite-hover {background:url(favorite-plus.gif) no-repeat; border:0; height:26px; width:26px;}
.qa-favorite-button {background-position: 0 -26px;}
.qa-favorite-hover,.qa-favorite-button:hover {background-position: 0 0px;}
.qa-unfavorite-button {background-position: 0 -52px;}
......@@ -413,4 +413,4 @@ h2 {font-size:16px; padding-top:12px; clear:both;}
.qa-tag-link:hover {text-decoration:none; background-color:#235272;}
.qa-avatar-image {border:0; vertical-align:middle;}
.qa-avatar-link,.qa-avatar-link:hover {text-decoration:none;}
.qa-favorite-image {background:url(favorite-plus.png) no-repeat; background-position: 0 -26px; border:0; margin:2px; height:26px; width:26px; vertical-align:middle; display:inline-block;}
.qa-favorite-image {background:url(favorite-plus.gif) no-repeat; background-position: 0 -26px; border:0; margin:2px; height:26px; width:26px; vertical-align:middle; display:inline-block;}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment