- При вынесении благодарности мы хотим, чтобы если за сообщение в теме благодарит автор темы или админ (модер) в кошелек благодаримого пользователя прибавлялись какое то (разное :) ) количество поинтов, а из кошелька благодарящего соответственно они же отнимались. Если же благодарность выносит простой читатель - тоже что то делать. (у меня например в этом случае денежных движений нет). При этом мы хотим не забыть отработать и обратную ситуацию (снятие благодарности). А число поинтов на каждое действо хотим задавать через АСП. Вы спросите, а в чем Смысл сего действа? хмм.. ну у меня работает для повышения мотивации писать такие сообщения, за которые остальные пользователи захотят Вас поблагодарить и поделятся своими поинтами, которые в рамках конторы приравнены к рублю. И которые (поинты) по достижению определенной суммы можно обналичить.
- Мы хотим, чтобы при достижении определенного числа благодарностей пользователю автоматически присваивалась медалька. Условия выдачи хотим задавать через АСП
Смысл? А тоже просто так - мотивация получить еще одну лычку. Юзеры же хотят чем то выделяться :) Ну и которая в свою очередь тоже может принести пойнтов..
Все нежеперечисленные действа помогут понять, как некоторые вещи работают в phpBB3, и аналогичный подход (не претендует на абсолютную верность и правильность и уж тем более пока не расчитыват на валидацию :) ) можно использовать и для других МОДов, или надстроек.
Обязательно: Для решения этих задачек нам нужен сам ПХПББ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');
Как видим, мы создали три поля, в которых можно хранить количество поинтов, использующихся при разных условиях. И четвертое поле, где мы можем определить, в какой момент начинать вручать медальку (медальки) юзеру. Однако сами по себе эти поля в таблице бессмысленны, их значения надо где то определять. Немного подумав, логично прийти к выводу, что так как это внутренные переменные, лучше всего их определить в ACP. Так как основной наш мод - это Thanks for post (Rating edition) я решил разместить определение этих величин в его админке (да простит меня Палыч автор этого волшебного МОДа).
для этого идем в темплейт 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>
пока все просто, не так ли ? но чтоб задаваемые там значения вменяемо отображались надо взять языковой файл language/ru/mods/info_acp_thanks.php
найти:
Код: Выделить всё
'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',
После этого мы имеем блок задания значений в .модули.благодарности.опции_конфигурации. Имеет смысл счас там их задать как Вы пожелаете. Следующим шагом берем из вложения образцы медалей, помещаем их в /images/medals. Идем в админку МОДа медалей и там их устанавливаем, запоминая ID.
ну вот, на этом моменте мы уже имеем определенный набор данных, можем задавать их, хранить их, пора бы перейти к их применению в наших шкурных интересах. Следствием установлено, что лучше всего все наши хотелки выполнять в момент, когда происходит выдача очередной благодарности.
Дело за малым, где ж это код то отрабатывает? Никакой магии, все просто. Просто у нас есть файл 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*/
Поясню - для чего мы сдублировали эту функцию, слегка ее упростив и кое что добавив. Первое - подразумевается, что гости благодарить не могут и кошелька не имеют. Второе - сама оригинальная функция возвращает массив с именами модераторов, но без USER_ID с которым нам прикольнее работать. Наша упрощенная функция добавляет в возвращаемый массив еще и этот самый USER_ID (а может когда нибудь придется и еще что нибудь добавить). Почему не сделать это в оригинальной функции? А потому что она оригинальная и вызывается много откуда, и обрабатывается "как есть" и при добавлении данных в массив они некрасиво начинают вылазить в разных местах. Давить это долго и нудно. Поэтому проще иметь свою адаптированную функцию для наших задач.
Далее нам ее надо вызвать в 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 */
А теперь добавим пару языковых переменных в language/ru/mods/thanks_mod.php
найти:
Код: Выделить всё
'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;
АХТУНГ: Встречается 2 раза! Соответсвенно нужно выполнить 2 добавления!
найти:
Код: Выделить всё
$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 ***
конструкции типа $tnx_medal_code=45; надо определить самостоятельно, указав там ID своих медалек.
найти:
Код: Выделить всё
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>');
Ну вот. можно пробовать. повторяющиеся куски кода можно вынести в отдельную функцию, или вообще прикреплять через include(), но, имхо, так понятнее.
Наверняка многое можно сделать проще. Буду рад если мне покажут как. Я не php программист - просто интересующийся, и просто решил разобраться и сделать то что мне самому было интересно.






