Публикация в группе: Кастомизация WP-Recall и Wordpress

В личку попросили поделиться системой опыта, которая организована на моем сайте, так что напишу это тут, может кому еще будет интересно.

Внимание! Если вы полный ноль в php и не понимаете что тут написано (или вы считаете что мой код - быдлокод) проходите мимо. Разжевать куда и что вставлять, если вы вообще ничего не понимаете я не смогу, в таком случае вам легче найти какой-то плагин с похожим функционалом (например cubepoints)

Система очень примитивная, но возможно кто-то возьмет её за базу и сделает нормальный плагин, ну или просто вдохновиться и напишет все сам.

Итак, начнем с формулы конвертирования опыта в уровень и обратно. В нашем случае это будет:

//Кол-во опыта на уровень
function getExpLevel($level) {
return pow($level, 10/7) * 100;
}
//Уровень по опыту
function getLevelExp($exp) {
return pow($exp / 100, 7/10);
}

 

Пример:

Опыта на уровень нам надо будет:

  1. 100
  2. 269
  3. 480
  4. 725
  5. 997
  6. 1293
  7. 1612
  8. 1950
  9. 2308
  10. 2683
  11. ....

А 37856 опыта будут соответствовать уровню 64

Вы можете самостоятельно отредактировать формулу, тогда кол-во опыта на уровень будет другое.

 

Теперь нам необходимо создать 2 таблицы (вы можете использовать для этого доп. поля профиля, мне удобнее отдельные таблицы)

В нашем случае это будут таблицы:

wp_day_user_exp (со столбцами user_id | date | exp) - таблица в которой будет хранится количества опыта набранного пользователем за сутки (дальше узнаете зачем)

wp_total_user_exp (со столбцами user_id | total_exp ) - таблица с общим опытом пользователя за все время

Теперь нам нужно как-то наполнять таблицы с опытом за активность на сайте. В нашем случае мы будет давать опыт за:

  1. Повышение рейтинга пользователя
  2. Если он добавил пост
  3. Если он добавил комментарий
// Повышаем exp пользователя если ему повышен рейтинг
add_action('rcl_insert_rating','rcl_increase_user_exp');
function rcl_increase_user_exp($data){
global $wpdb;
$date = date('Y-m-d', strtotime("+3 hours")); // сегодня в формате 2016-02-29 (+3 часа для МСК)
$exp = $data['rating_value'] * 2; // Увеличиваем опыт на значение рейтинга х 2
$user_id = $data['object_author'];
$exptodb = $wpdb->query("INSERT INTO wp_total_user_exp SET user_id = $user_id,total_exp = $exp 
ON DUPLICATE KEY UPDATE total_exp=total_exp + $exp"); // заносим общий рейтинг юзера
$exptodbbyday = $wpdb->query("INSERT INTO wp_day_user_exp SET user_id = $user_id, date = '$date', exp = $exp 
ON DUPLICATE KEY UPDATE exp=exp + $exp"); // заносим суточный рейтинг юзера
}
// Повышаем exp пользователя если он добавит пост любого типа
add_action('transition_post_status', 'add_post_exp', '100', '3');// хук срабатывающий при изменении статуса поста
function add_post_exp($new_status, $old_status, $post){
 if ($new_status == 'publish' && $old_status != 'publish') { // добавляем рейтинг только если пост опубликован
// а не обновлен
 post_increase_user_exp($post);
 }
}
function post_increase_user_exp( $post ) {
global $wpdb;
$date = date('Y-m-d', strtotime("+3 hours")); // сегодня в формате 2016-02-29 (+3 часа для МСК)
$user_id = $post->post_author;
$posttip = get_post_type($post->ID);
if ($posttip == 'post') $exp = 30; // За пост типа "post" даем 30 опыта
if ($posttip == 'video') $exp = 5; // За пост типа "video" даем 5 опыта
if ($posttip == 'reply') $exp = 5; // За ответ на форуме bbpress даем 5 опыта
if ($posttip == 'topic') $exp = 20; // За новую тему на форуме bbpress даем 20 опыта
$exptodb = $wpdb->query("INSERT INTO wp_total_user_exp SET user_id = $user_id,total_exp = $exp 
ON DUPLICATE KEY UPDATE total_exp=total_exp + $exp"); // заносим общий рейтинг юзера
$exptodbbyday = $wpdb->query("INSERT INTO wp_day_user_exp SET user_id = $user_id, date = '$date', exp = $exp 
ON DUPLICATE KEY UPDATE exp=exp + $exp"); // заносим суточный рейтинг юзера
}
// Повышаем exp пользователя если он добавил комментарий
add_action( 'comment_post', 'comment_increase_user_exp', 10, 2 );
function comment_increase_user_exp( $comment_ID, $comment_approved ) {
if( 1 === $comment_approved ){
global $wpdb;
$date = date('Y-m-d', strtotime("+3 hours")); // сегодня в формате 2016-02-29 (+3 часа для МСК)
$comment = get_comment( $comment_ID );
$user_id = $comment->user_id;
$exp = 5; // за комментарий даем 5 опыта
$exptodb = $wpdb->query("INSERT INTO wp_total_user_exp SET user_id = $user_id,total_exp = $exp 
ON DUPLICATE KEY UPDATE total_exp=total_exp + $exp"); // заносим общий рейтинг юзера
$exptodbbyday = $wpdb->query("INSERT INTO wp_day_user_exp SET user_id = $user_id, date = '$date', exp = $exp 
ON DUPLICATE KEY UPDATE exp=exp + $exp"); // заносим суточный рейтинг юзера
}
}

 

Теперь нам нужна функция которая будет переводить общий опыт пользователя из базы в уровень, вычислять опыт на следующий уровень и возвращать результат в виде готового html кода

 

function total_user_exp( $user_id ) {
$cacheID = 'total_user_exp_'.$user_id;
$exparray = wp_cache_get( $cacheID ); // Смотрим есть ли значение в кеше (если у вас стоит плагин 
// объектного кеширования)
if ( false === $exparray ) {
// Берем из базы общий опыт пользователя
$totalexp = $wpdb->get_var("SELECT total_exp FROM wp_total_user_exp WHERE user_id = $user_id");
// Переводим опыт в уровень 
$mylevel = floor(getLevelExp($totalexp)); // мой уровень
$exptomylevel = round(getExpLevel($mylevel)); // опыта на мой уровень
$exptonextlevel = round(getExpLevel($mylevel+1)); // опыта на сл. уровень
// Вычисляем сколько % набрано для следующего уровня
$percenyearned = round((($totalexp - $exptomylevel) / ($exptonextlevel - $exptomylevel))*100, 2);

//Вычисляем ранг по уровню
/* Новичок - 0
Пользователь - 5
Активный - 15
Гигант мысли - 30
Маньяк - 45
Старейшина - 60
Знаток - 75
Ветеран - 100
Генерал - 125
Предводитель - 150 */

if ($mylevel < 5) {$rank='Новичок';}
elseif ($mylevel < 15) {$rank='Пользователь';}
elseif ($mylevel < 30) {$rank='Активный';}
elseif ($mylevel < 45) {$rank='Гигант мысли';}
elseif ($mylevel < 60) {$rank='Маньяк';}
elseif ($mylevel < 75) {$rank='Старейшина';}
elseif ($mylevel < 100) {$rank='Знаток';}
elseif ($mylevel < 125) {$rank='Ветеран';}
elseif ($mylevel < 150) {$rank='Генерал';}
elseif ($mylevel < 200) {$rank='Предводитель';}

//Массив с данными по уровню о пользователе $user_id
$exparray = array(
"mylevel" => $mylevel,
"myexp" => $totalexp,
"exptonextlevel" => $exptonextlevel,
"percenyearned" => $percenyearned,
"rank" => $rank
);
wp_cache_set( $cacheID, $exparray, '', '360'); // Если кеша нет или время вышло - перезаписываем его
}

$result = "<p class='totalexpp' title='".$exparray['rank']."'>Уровень ".$exparray['mylevel']."</p>
<div class='totalexpdiv' title='exp: ".$exparray['myexp']."/".$exparray['exptonextlevel']."'>
<p>".$exparray['percenyearned']."%</p>
<div class='totalexpdivdiv' style='width:".$exparray['percenyearned']."%;'></div>
</div>";
// Возвращаем результат
return $result;
}

Мои css стили для результата:

.totalexpp {
font-size: 13px!important;
margin: 10px 0 0px 0!important;
}

.totalexpdiv {
outline: 1px solid #2A2A2A;
display: block;
height: 15px;
width: 100%;
background-color: #D2D2D2;
box-shadow: inset 0 3px 3px #E8E8E8;
position: relative;
text-align: center;
margin-top: 10px;
}
.totalexpdiv>p {
position: absolute;
width: 100%;
color: #FFF;
text-shadow: 1px 1px 1px #000;
font-size: 12px;
line-height: 14px;
}
.totalexpdivdiv{
display: block;
height: 15px;
box-shadow: inset 0 3px 3px #DA8686;
background-color: #822227;
}

В результате функция:

total_user_exp( $user_id ); // передаем id пользователя

Вернет что-то типа:

<p class="totalexpp" title="Предводитель">Уровень 169</p>
<div class="totalexpdiv" title="exp: 152388/153587">
<p>6.98%</p>
<div class="totalexpdivdiv" style="width:6.98%;"></div>
</div>

 

Что будет выглядеть как:

 

 

Ну и небольшой бонус. Если вы помните, то мы создавали таблицу с опытом который набирает пользователь за сутки. Давайте используем её содержимое что бы вывести пользователей с наибольшим числом опыта за неделю.

// Берем из базы пользователей с суммой опыта за неделю
$allusertop = $wpdb->get_results("SELECT user_id, SUM(exp) FROM wp_day_user_exp 
WHERE date>=DATE_ADD(CURRENT_TIMESTAMP,INTERVAL -7 DAY) GROUP BY user_id", ARRAY_N);

foreach ($allusertop as $oneuser) { // Берем только тех у кого опыт > 0
if ($oneuser[1] > 0) {
$usertop[$oneuser[0]] = $oneuser[1];
}
}

arsort($usertop); // Сортируем пользователей по убыванию опыта

echo "<ul class='top-user'>";

foreach ($usertop as $user_id => $exp) {
$i++;
echo "<li>";
echo "<figure>".get_avatar( $user_id, 120 )."<p>".$i."</p></figure>";
echo "<a href='".get_author_posts_url($user_id)."'>".get_the_author_meta('display_name', $user_id )."</a>";
echo "<p> Набрано опыта: ".$exp."</p>";
echo "</li>";
}

echo "</ul>";

 

В результате получим что-то типа этого:

 

 

P.S.

Как вы могли заметить у нас таблицы

wp_day_user_exp

wp_total_user_exp

имеют префикс wp - если у вас он другой, либо впишите свой, либо используйте

$wpdb->prefix

 

4

Автор публикации

не в сети 2 дня

Preci

1 493
Telegram: https://t.me/preci_123
Комментарии: 495Публикации: 83Регистрация: 11-11-2014Продаж/Покупок: 0/0