- При вынесении благодарности мы хотим, чтобы если за сообщение в теме благодарит автор темы или админ (модер) в кошелек благодаримого пользователя прибавлялись какое то (разное :) ) количество поинтов, а из кошелька благодарящего соответственно они же отнимались. Если же благодарность выносит простой читатель - тоже что то делать. (у меня например в этом случае денежных движений нет). При этом мы хотим не забыть отработать и обратную ситуацию (снятие благодарности). А число поинтов на каждое действо хотим задавать через АСП. Вы спросите, а в чем Смысл сего действа? хмм.. ну у меня работает для повышения мотивации писать такие сообщения, за которые остальные пользователи захотят Вас поблагодарить и поделятся своими поинтами, которые в рамках конторы приравнены к рублю. И которые (поинты) по достижению определенной суммы можно обналичить.
- Мы хотим, чтобы при достижении определенного числа благодарностей пользователю автоматически присваивалась медалька. Условия выдачи хотим задавать через АСП
Смысл? А тоже просто так - мотивация получить еще одну лычку. Юзеры же хотят чем то выделяться :) Ну и которая в свою очередь тоже может принести пойнтов..
Обязательно: Для решения этих задачек нам нужен сам ПХПББ3 который 3.0.7, установленные моды Thanks for post 1.2.8, Ultimate Points 1.0.7 и Medal System mod. Которые уже делают за нас многие забавные вещи, и нам останется только воспользоваться их возможностями и заставить делать то что мы хотим, т.е. просто их подружить. это не так сложно как кажется, после обдумывания задачи писание кода заняло пару часов включая тестирование. Тем более глобальное вмешательство в код происходит в файле функций только одного мода, и по мелочи в файлы ядра. Также нам нужен доступ в phpMyAdmin, ACP форума, FTP доступ к файлам форума и редактор типа PSPAD.
Примечание: надеюсь всем понятно, это не МОД, это была надстройка аж над пятью МОДами, здесь упрощенная до настройки над тремя модами. Писалось для себя и под себя (некоторые вещи могут показаться избыточными) и у меня вроде работает, но используйте на свой страх и риск, никаких гарантий :)
Пинки и замечания тем не менее принимаются и приветствуются. как и благодарности :)
Итак, первое что нам надо сделать, это выяснить где хранятся данные. а данные хранятся, как это ни странно звучит, в SQL базе вашего форума, доступной через phpMyAdmin (имхо, если вы не знаете что это такое, дальше можно не читать). Если взглянуть на нее даже невооруженным глазом, то видно что база состоит из кучи таблиц, чьи имена зачастую говорят сами за себя. Многие данные взять оттуда можно разными путями. Что же мы можем выяснить, а то что конфигурационные данные мода благодарностей лежат в *_config (алиас, установленный в includes/constants.php CONFIG_TABLE, будем дальше использовать алиасы - интересующиеся - добро пожаловать в includes/constants.php), сами благодарности уютно расположились в табличке THANKS_TABLE, юзеровские поинты в живут в табличке USERS_TABLE (кстати, мне показалось что массив phpBB3 $user просто хапает эту табличку в себя), а полученные медали в можно найти в MEDALS_AWARDED_TABLE. В общем то больше ничего нам и не надо знать на текущем этапе.
Теперь нам надо добавить несколько полей в CONFIG_TABLE. Делается это через phpMyAdmin используя вкладку "SQL" и
выполняем
АХТУНГ: ХХХ="имя вашей базы", УУУ=префикс вашей таблицы. (обычно по умолчанию phpbb, если не изменяли при установке !!!
Код: Выделить всё
INSERT INTO `ХХХ`.`УУУ_config` (`config_name` ,`config_value` ,`is_dynamic` )
VALUES ('thanks_points_for_post_adm', '', '0');
INSERT INTO `ХХХ`.`УУУ_config` (`config_name` ,`config_value` ,`is_dynamic` )
VALUES ('thanks_points_for_post_aut', '', '0');
INSERT INTO `ХХХ`.`УУУ_config` (`config_name` ,`config_value` ,`is_dynamic` )
VALUES ('thanks_points_for_post_usr', '', '0');
INSERT INTO `ХХХ`.`УУУ_config` (`config_name` ,`config_value` ,`is_dynamic` )
VALUES ('thanks_medal_step', '', '0');
для этого идем в темплейт adm/style/acp_thanks.html и
найти:
Код: Выделить всё
<dl>
<dt><label for="thanks_number_post">{L_THANKS_NUMBER_POST}:</label><br /><span>{L_THANKS_NUMBER_POST_EXPLAIN}</span></dt>
<dd><input id="thanks_number_post" name="thanks_number_post" value="{THANKS_NUMBER_POST}" type="text" /></dd>
</dl>
Код: Выделить всё
<h3><font color="red">{L_ACP_THANKS_POINTS}.</font></h3><br />
<dl>
<dt><label for="thanks_points_for_post_adm">{L_THANKS_POINTS_FOR_POST_ADM}:</label><br /></dt>
<dd><input id="thanks_points_for_post_adm" name="thanks_points_for_post_adm" value="{THANKS_POINTS_FOR_POST_ADM}" type="text" /></dd>
</dl>
<dl>
<dt><label for="thanks_points_for_post_aut">{L_THANKS_POINTS_FOR_POST_AUT}:</label><br /></dt>
<dd><input id="thanks_points_for_post_aut" name="thanks_points_for_post_aut" value="{THANKS_POINTS_FOR_POST_AUT}" type="text" /></dd>
</dl>
<dl>
<dt><label for="thanks_points_for_post_usr">{L_THANKS_POINTS_FOR_POST_USR}:</label><br /></dt>
<dd><input id="thanks_points_for_post_usr" name="thanks_points_for_post_usr" value="{THANKS_POINTS_FOR_POST_USR}" type="text" /></dd>
</dl>
<dl>
<dt><label for="thanks_medal_step">{L_THANKS_MEDAL_STEP}:</label><br /><span>{L_THANKS_MEDAL_STEP_EXPLAIN}</span></dt>
<dd><input id="thanks_medal_step" name="thanks_medal_step" value="{THANKS_MEDAL_STEP}" type="text" /></dd>
</dl>
найти:
Код: Выделить всё
'THANKS_NUMBER_POST'вставить после всей строки с новой строки
Код: Выделить всё
'ACP_THANKS_POINTS' => 'Поинты за благодарности',
'THANKS_POINTS_FOR_POST_ADM' => 'Поинтов за благодарность от админа',
'THANKS_POINTS_FOR_POST_AUT' => 'Поинтов за благодарность от автора',
'THANKS_POINTS_FOR_POST_USR' => 'Поинтов за благодарность от юзера',
'THANKS_MEDAL_STEP' => 'Начальное значение для медалей',
'THANKS_MEDAL_STEP_EXPLAIN' => 'Начальное значение количества благодарностей для медалей. Остальныезначения для награждений будут вычислены как степень двойки.',
ну вот, осмысленные записи в админке у нас появились (в самом низу первой настроечной вкладки МОДа <<Благодарности>-><Опции конфигурации>), но чтоб устанавливаемые там данные при нажатии на [Отправить] попали в SQL базу на свое место в табличке и там сохранились, нужно еще сделать следующее в связанном файле includes/acp/acp_thanks.php
найти:
Код: Выделить всё
'thanks_number_post' => 'THANKS_NUMBER_POST',Код: Выделить всё
'thanks_points_for_post_adm' => 'THANKS_POINTS_FOR_POST_ADM',
'thanks_points_for_post_aut' => 'THANKS_POINTS_FOR_POST_AUT',
'thanks_points_for_post_usr' => 'THANKS_POINTS_FOR_POST_USR',
'thanks_medal_step' => 'THANKS_MEDAL_STEP',
ну вот, на этом моменте мы уже имеем определенный набор данных, можем задавать их, хранить их, пора бы перейти к их применению в наших шкурных интересах. Следствием установлено, что лучше всего все наши хотелки выполнять в момент, когда происходит выдача очередной благодарности.
Дело за малым, где ж это код то отрабатывает? Никакой магии, все просто. Просто у нас есть файл includes/function_thanks.php - где и предусмотрена обработка нажатия кнопочки дать-отобрать благодарность. Там мы после события вынесения благодарности должны отловить кто благодарит, кого благодарят, текущее количество благодарностей у благодаримого юзера, взять по условию значение применяемый поинтов и прибавить/отнять их, при совпадении определенного условия выдать медальку. Большую часть работы за нас уже сделали, много что уже определено, надо только всем этим воспользоваться. У меня предусмотрена возможность отрицательного баланса пойнтов для некоторых других целей (увязаны еще некоторые другие МОДы), поэтому я не буду контролировать хватает ли у юзера пойнтов или нет при вынесении благодарности. Но сделать контроль и этого - проще простого, как вы понимаете. В общем вы будете смеятся, но все делается в одном месте для начисления и в одном для снятия. (ну плюс еще объявление нужных нам глобалов)
АХТУНГ: к сожалению, Medal System Mod не предусматривает автоматической выдачи медалей, но описанным ниже путем можно привязать автоматическую выдачу медали к любому событию.
Я не знаю в какую категорию и какой по счету Вами будет размещена медаль (медали), диктовать их месторасположение наверное тоже не дело, а вычислять это все на текущий момент лениво (может и догадаюсь когда нить) придется привязывать некоторые моменты вручную в коде, хотя как известно - это не очень хорошо.... :(
но к делу. Для начала надо немного похимичить с includes/function_display.php и viewtopic.php
Действо совершаемое нами на первый взгляд глупое, но мне показалось что так будет проще и понятнее, тем более использовалось в других местах.
includes/function_display.php
найти:
Код: Выделить всё
function get_moderators(&$forum_moderators, $forum_id = false)
{
*** здесь код оригинальной функции, искать по названию и закрывающим скобкам ***
return;
}
Код: Выделить всё
/* Obtain IDS of moderators of each forum
* Added by DennyTX */
function get_moderators_ids(&$forum_moderators_ids, $forum_id = false)
{
global $config, $template, $db, $phpbb_root_path, $phpEx, $user, $auth;
$forum_id_ary = array();
if ($forum_id !== false)
{
if (!is_array($forum_id))
{
$forum_id = array($forum_id);
}
$forum_id_ary = array_flip($forum_id);
}
$sql_array = array(
'SELECT' => 'm.*, u.user_colour, g.group_colour, g.group_type',
'FROM' => array(
MODERATOR_CACHE_TABLE => 'm',
),
'LEFT_JOIN' => array(
array(
'FROM' => array(USERS_TABLE => 'u'),
'ON' => 'm.user_id = u.user_id',
),
array(
'FROM' => array(GROUPS_TABLE => 'g'),
'ON' => 'm.group_id = g.group_id',
),
),
'WHERE' => 'm.display_on_index = 1',
);
$sql = $db->sql_build_query('SELECT', $sql_array);
$result = $db->sql_query($sql, 3600);
while ($row = $db->sql_fetchrow($result))
{
$f_id = (int) $row['forum_id'];
if (!isset($forum_id_ary[$f_id]))
{
continue;
}
if (!empty($row['user_id']))
{
$forum_moderators_ids[$f_id][] = get_username_string('full', $row['user_id'], $row['username'], $row['user_colour']);
$forum_moderators_ids[$f_id][] = $row['user_id'];
}
}
$db->sql_freeresult($result);
return;
}
/* end DennyTX addition*/
Далее нам ее надо вызвать в viewtopic.php
найти:
Код: Выделить всё
// Moderators
$forum_moderators = array();
if ($config['load_moderators'])
{
get_moderators($forum_moderators, $forum_id);
}
Код: Выделить всё
/* added by DennyTX */
$forum_moderators_ids = array();
if ($config['load_moderators'])
{
get_moderators_ids($forum_moderators_ids, $forum_id);
}
/* end DennyTX addition */
найти:
Код: Выделить всё
'THANKS_INFO_REMOVE' => 'Вы отменили благодарность автору',
Код: Выделить всё
//Added by DennyTX
'THANKS_POINTS_INFO_ADD' => 'И выдали ему из своего кошелька',
'THANKS_POINTS_INFO_REMOVE' => 'И отобрали у него свои несчастные',
берем includes/function_thanks.php .
найти:
Код: Выделить всё
global $db, $user, $phpbb_root_path, $phpEx, $forum_id, $config;
Код: Выделить всё
// Added by DennyTX
global $forum_moderators_ids, $topic_data, $auth;
найти:
Код: Выделить всё
$sql = 'INSERT INTO ' . THANKS_TABLE . ' ' . $db->sql_build_array('INSERT', array(
'user_id' => $user_id,
'post_id' => $post_id,
'poster_id' => $to_id,
'topic_id' => $row['topic_id'],
'forum_id' => $row['forum_id'],
'thanks_time' => time()
));
$db->sql_query($sql);
вставить после
здесь была ошибка. поправлено
Код: Выделить всё
// added by DennyTX
// посчитаем число благодарностей (не надо ли выдать медальку?)
$sql = 'SELECT count(*) from ' . THANKS_TABLE .
' where poster_id=' . $to_id;
$result = $db->sql_query($sql);
$current_thanks_q = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
// запросим данные
$get_thanks_options = $db->sql_query(
'SELECT config_name,config_value from ' . CONFIG_TABLE .
' where config_name="thanks_medal_step"' .
' union ' .
'SELECT config_name,config_value from ' . CONFIG_TABLE .
' where config_name like "thanks_points_for_post_%"' .
' order by 1'
);
$get_tnx_medal_step = $db->sql_fetchrow($get_thanks_options);
$get_tnx_medal_step = $get_tnx_medal_step['config_value'];
$get_thanks_points_adm = $db->sql_fetchrow($get_thanks_options);
$get_thanks_points_adm = $get_thanks_points_adm['config_value'];
$get_thanks_points_aut = $db->sql_fetchrow($get_thanks_options);
$get_thanks_points_aut = $get_thanks_points_aut['config_value'];
$get_thanks_points_usr = $db->sql_fetchrow($get_thanks_options);
$get_thanks_points_usr = $get_thanks_points_usr['config_value'];
$points_name = $db->sql_query(
'SELECT config_name,config_value from ' . CONFIG_TABLE .
' where config_name="points_name"'
);
$points_name = $db->sql_fetchrow($points_name);
$points_name = $points_name['config_value'];
// определим какие хотим давать медальки
if ($current_thanks_q['count(*)'] == $get_tnx_medal_step)
$tnx_medal_code=45;
elseif ($current_thanks_q['count(*)'] == $get_tnx_medal_step*2)
$tnx_medal_code=46;
elseif ($current_thanks_q['count(*)'] == $get_tnx_medal_step*4)
$tnx_medal_code=47;
else
$tnx_medal_code=false;
// если есть событие на количество благодарностей, то выдадим медальку
if($tnx_medal_code)
{
// сначала проверим, нет ли уже у юзера такой медали
$sql = 'SELECT * from ' . MEDALS_AWARDED_TABLE .
' where medal_id=' . $tnx_medal_code . ' and user_id=' . $to_id .
" limit 1";
$result = $db->sql_query($sql);
$user_has_it = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
// если нужной медальки нет, выдадим
$uid = $bitfield = '';
if($user_has_it===false)
{
$sql = 'INSERT INTO ' . MEDALS_AWARDED_TABLE . ' ' . $db->sql_build_array('INSERT', array(
'medal_id' => $tnx_medal_code,
'user_id' => $to_id,
'awarder_id' => $user_id,
'awarder_un' => "Robot",
'awarder_color' => "AA0000",
'nominated' => 0,
'nominated_reason' => "Auto",
'time' => time(),
'bbuid' => $uid,
'bitfield' => $bitfield,
));
$db->sql_query($sql);
}
}
// добавляем денежку при выдачи благодарности из кошелька того кто благодарит
// в кощелек того, кого благодарят
// определим нужный нам статус пользователя
$current_moders = array();
$a = $forum_moderators_ids[$forum_id];
for($i=1;$i<count($a);$i+=2)
{
$current_moders[$a[$i]] = true;
}
if($user->data['user_id'] == $topic_data['topic_poster'])
// благодарит автор темы
$thanks_points=$get_thanks_points_aut;
elseif(isset($current_moders[$user->data['user_id']]))
// благодарит модератор форума
$thanks_points=$get_thanks_points_adm;
elseif($user->data['group_id'] == 5)
// благодарит администратор
$thanks_points=$get_thanks_points_adm;
else
// благодарит простой пользователь
$thanks_points=$get_thanks_points_usr;
if ($thanks_points)
{
$sql = "UPDATE " . USERS_TABLE . "
SET user_points = user_points - $thanks_points
WHERE user_id = $user_id" ;
$db->sql_query($sql);
$sql = "UPDATE " . USERS_TABLE . "
SET user_points = user_points + $thanks_points
WHERE user_id = $to_id" ;
$db->sql_query($sql);
}
//*** end DennyTX addition ***
найти:
Код: Выделить всё
trigger_error($user->lang['THANKS_INFO_'.$lang_act] . '<br /><br /><a href="'.append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&p=$post_id#p$post_id").'">'.$user->lang['RETURN_POST'].'</a>');
Код: Выделить всё
trigger_error($user->lang['THANKS_INFO_'.$lang_act] ." ". $user->lang['THANKS_POINTS_INFO_ADD'] ." ". $thanks_points ." ". $points_name . '<br /><br /><a href="'.append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&p=$post_id#p$post_id").'">'.$user->lang['RETURN_POST'].'</a>');
найти:
Код: Выделить всё
if (confirm_box(true))
{
if ($user->data['user_type'] != USER_IGNORE && !empty($to_id))
{
$sql = "DELETE FROM " . THANKS_TABLE . '
WHERE post_id ='. (int) $post_id ." AND user_id = " . $user->data['user_id'];
$db->sql_query($sql);
Код: Выделить всё
// Added by DennyTX
//** убираем ранее выданную денежку при снятии благодарности
// запросим данные
$get_thanks_options = $db->sql_query(
'SELECT config_name,config_value from ' . CONFIG_TABLE .
' where config_name="thanks_medal_step"' .
' union ' .
'SELECT config_name,config_value from ' . CONFIG_TABLE .
' where config_name like "thanks_points_for_post_%"' .
' order by 1'
);
$get_tnx_medal_step = $db->sql_fetchrow($get_thanks_options);
$get_tnx_medal_step = $get_tnx_medal_step['config_value'];
$get_thanks_points_adm = $db->sql_fetchrow($get_thanks_options);
$get_thanks_points_adm = $get_thanks_points_adm['config_value'];
$get_thanks_points_aut = $db->sql_fetchrow($get_thanks_options);
$get_thanks_points_aut = $get_thanks_points_aut['config_value'];
$get_thanks_points_usr = $db->sql_fetchrow($get_thanks_options);
$get_thanks_points_usr = $get_thanks_points_usr['config_value'];
$points_name = $db->sql_query(
'SELECT config_name,config_value from ' . CONFIG_TABLE .
' where config_name="points_name"'
);
$points_name = $db->sql_fetchrow($points_name);
$points_name = $points_name['config_value'];
// определим нужный нам статус пользователя
$current_moders = array();
$a = $forum_moderators_ids[$forum_id];
for($i=1;$i<count($a);$i+=2)
{
$current_moders[$a[$i]] = true;
}
if($user->data['user_id'] == $topic_data['topic_poster'])
// благодарит автор темы
$thanks_points=$get_thanks_points_aut;
elseif(isset($current_moders[$user->data['user_id']]))
// благодарит модератор форума
$thanks_points=$get_thanks_points_adm;
elseif($user->data['group_id'] == 5)
// благодарит администратор
$thanks_points=$get_thanks_points_adm;
else
// благодарит простой пользователь
$thanks_points=$get_thanks_points_usr;
if ($thanks_points)
{
$sql = "UPDATE " . USERS_TABLE . "
SET user_points = user_points + $thanks_points
WHERE user_id = $user_id" ;
$db->sql_query($sql);
$sql = "UPDATE " . USERS_TABLE . "
SET user_points = user_points - $thanks_points
WHERE user_id = $to_id" ;
$db->sql_query($sql);
}
//*** end DennyTX addition ***
Код: Выделить всё
trigger_error($user->lang['THANKS_INFO_'.$lang_act]. '<br /><br /><a href="'.append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&p=$post_id#p$post_id").'">'.$user->lang['RETURN_POST'].'</a>');
Код: Выделить всё
trigger_error($user->lang['THANKS_INFO_'.$lang_act] ." ". $user->lang['THANKS_POINTS_INFO_REMOVE'] ." ". $thanks_points ." ". $points_name . '<br /><br /><a href="'.append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&p=$post_id#p$post_id").'">'.$user->lang['RETURN_POST'].'</a>');
Наверняка многое можно сделать проще. Буду рад если мне покажут как. Я не php программист - просто интересующийся, и просто решил разобраться и сделать то что мне самому было интересно.

