Commit 4000262c authored by Vadim's avatar Vadim

Version 2.0

Добавлен рейтинг по голосам ("звездочки")
parent cda075aa
......@@ -3,7 +3,7 @@
Plugin Name: Bg Az-Counter
Plugin URI: https://bogaiskov.ru
Description: Подсчет количества посещений страниц на базе stat.azbyka.ru
Version: 1.3.0
Version: 2.0
Author: VBog
Author URI: https://bogaiskov.ru
License: GPL2
......@@ -37,15 +37,22 @@
if ( !defined('ABSPATH') ) {
die( 'Sorry, you are not allowed to access this page directly.' );
}
define('BG_COUNTER_VERSION', '1.3.0');
$bg_counter_plugin_data = get_plugin_data(__FILE__);
define('BG_COUNTER_VERSION', $bg_counter_plugin_data['Version']);
define('BG_COUNTER_LOG', dirname(__FILE__ ).'/bg_counter.log');
define('BG_COUNTER_STAT_COUNTERS','https://stat.azbyka.ru/counters');
define('BG_COUNTER_STAT_RAITING','https://stat.azbyka.ru/rating');
define('BG_COUNTER_STAT_RATING','https://stat.azbyka.ru/rating');
define('BG_COUNTER_STAT_RATE','https://stat.azbyka.ru/rate');
define('BG_COUNTER_STAT_SCORE','https://stat.azbyka.ru/item-score');
define('BG_COUNTER_STAT_SCORELIST','https://stat.azbyka.ru/scores-list');
define('BG_COUNTER_STAT_SET','https://stat.azbyka.ru/set-counter');
define('BG_COUNTER_STAT_SET_RATINGS','https://stat.azbyka.ru/set-rating');
define('BG_COUNTER_REALTIME_VIEW','wss://stat.azbyka.ru/realtime-view');
$upload_dir = wp_upload_dir();
define('BG_COUNTER_ARCHIVE',str_replace(ABSPATH, '', $upload_dir['basedir']).'/bg_az_counter.json');
define('BG_COUNTER_ARCHIVE_COUNTER',str_replace(ABSPATH, '', $upload_dir['basedir']).'/bg_az_counter.json');
define('BG_COUNTER_ARCHIVE_RATING',str_replace(ABSPATH, '', $upload_dir['basedir']).'/bg_az_rating.json');
define('BG_COUNTER_DEFECT',str_replace(ABSPATH, '', $upload_dir['basedir']).'/bg_az_counter_defect.json');
// Определяем имя проекта
if (!isset($project)) {
......@@ -88,14 +95,22 @@ function bg_counter_enqueue_frontend_scripts () {
}
}
wp_enqueue_script( 'bg_counter_websocket', plugins_url( 'js/reconnecting-websocket.min.js', __FILE__ ), false, BG_COUNTER_VERSION, true );
wp_enqueue_script( 'bg_counter_rating', plugins_url( 'js/rating.js', __FILE__ ), false, BG_COUNTER_VERSION, true );
wp_enqueue_script( 'bg_counter_proc', plugins_url( 'js/counter.js', __FILE__ ), false, BG_COUNTER_VERSION, true );
wp_localize_script( 'bg_counter_proc', 'bg_counter',
array(
'counterurl' => BG_COUNTER_STAT_COUNTERS, // Всегда 'https://stat.azbyka.ru/counters'
'rateurl' => BG_COUNTER_STAT_RATE, // Всегда 'https://stat.azbyka.ru/rate'
'scoreurl' => BG_COUNTER_STAT_SCORE, // Всегда 'https://stat.azbyka.ru/item-score'
'websocket' => BG_COUNTER_REALTIME_VIEW, // Всегда 'wss://stat.azbyka.ru/realtime-view'
'project' => $project, // Имя текущего проекта, например, '/propovedi'
'type' => $type, // Пока только 'post' или пусто
'ID' => $postID, // ID поста
'votes5' => 'голосов',
'votes2' => 'голоcа',
'vote1' => 'голос',
'voted' => 'Вы уже проголосовали',
'price' => array("ужасно", "плохо", "удовлетворительно", "хорошо", "отлично"),
'debug' => ((int) $option['debug'])?true:false // Выводить или нет инфу в консоль
)
);
......@@ -113,209 +128,13 @@ function bg_counter_deinstall() {
delete_option('bg_pvc_loaded');
delete_option('bg_wppp_loaded');
delete_option('bg_wppm_loaded');
delete_option('bg_bgar_loaded');
delete_option('bg_archive_status');
delete_option('bg_counter_period');
}
/*****************************************************************************************
GET /rating/<path>
Рейтинг. Возвращает непосредственных потомков, упорядоченных по убыванию
value.
Доступные параметры:
limit - ограничение на количество возвращаемых потомков. По умолчанию: 100
offset - сколько элементов в начале пропустить. По умолчанию: 0
limit/offset работают по такому же принципу, как и в SQL.
Пример запроса:
GET /rating/project/test/author/1?limit=5&offset=3
Пример ответа:
{
"success":true,
"data":[
{"id":"6","type":"book","value":11},
{"id":"7","type":"book","value":7},
{"id":"5","type":"book","value":1},
{"id":"4","type":"book","value":1},
{"id":"3","type":"book","value":1}
]
}
Если счётчик не существует, возвращает пустой массив потомков.
******************************************************************************************/
function getPopularPosts ($limit, $offset=0, $number=false) {
global $project;
$option = get_option('bg_counter_options');
$result = wp_remote_get (BG_COUNTER_STAT_RAITING.$project."?limit=".$limit."&offset=".$offset."&type=post");
if( is_wp_error( $result ) ) {
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." РЕЙТИНГ. Ошибка при получении данных с сервера: ".$result->get_error_message(), 3, BG_COUNTER_LOG ); // сообщение ошибки
error_log( " " .$result->get_error_code(), 3, BG_COUNTER_LOG ); // ключ ошибки
return false;
}
if (($code = wp_remote_retrieve_response_code( $result )) != 200) {
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." РЕЙТИНГ. Сервер вернул код ошибки: ".$code, 3, BG_COUNTER_LOG ); // сообщение ошибки
error_log( " " .wp_remote_retrieve_response_message( $result ), 3, BG_COUNTER_LOG ); // ключ ошибки
return false;
}
$json = wp_remote_retrieve_body($result);
$response = json_decode($json, false);
if ($response->success == true){
$the_key='getPopularPostss_key';
if(false===($quote=get_transient($the_key))) {
if ($number) $quote = '<ol class="bg-az-top-posts">'. PHP_EOL;
else $quote = '<ul class="bg-az-top-posts">'. PHP_EOL;
foreach ($response->data as $p) {
if ($p->type!='post') continue;
$id = intval($p->id);
if (!$id) continue;
$post = get_post($id);
if (!$post) continue;
$title = $post->post_title;
$link = '<a href="'. get_permalink($post).'" title="'.$title.'" data-ID="'.$p->id.'" data-type="'.$p->type.'" data-value="'.$p->value.'" data-status="'.$post->post_status.'">'.$title.'</a>';
$quote .= '<li>'.$link.' - <span class="bg-az-count">'.number_format($p->value, 0, ',', '&nbsp;').'</span></li>'. PHP_EOL;
}
if ($number) $quote .= '</ol>'. PHP_EOL;
else $quote .= '</ul>'. PHP_EOL;
set_transient( $the_key, $quote, $option['period'] );
}
return $quote;
} else {
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." РЕЙТИНГ. Сервер вернул ответ неудачи: ".print_r($response, true), 3, BG_COUNTER_LOG );
return false;
}
}
/*****************************************************************************************
POST /set-counter/<path>
Задаёт значение счётчика и создаёт его, если счётчик не существовал.
Предназначено для импорта данных и должно быть закрыто от внешних клиентов.
Пример запроса:
POST /set-counter/project/test/author/1/book/3
Тело: {"counter": 3}
Пример ответа:
{"success": true}
******************************************************************************************/
// Установить 1 счетчик
function setCount ($path, $counter) {
global $project;
$result = wp_remote_post (BG_COUNTER_STAT_SET.$project.$path, array('body' => '{"counter": '.$counter.'}'));
if( is_wp_error( $result ) ) {
echo "<br>".$result->get_error_message(); // сообщение ошибки
echo "<br>".$result->get_error_code(); // ключ ошибки
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." СЧЁТЧИК. Ошибка при получении данных с сервера: ".$result->get_error_message(), 3, BG_COUNTER_LOG ); // сообщение ошибки
error_log( " " .$result->get_error_code(), 3, BG_COUNTER_LOG ); // ключ ошибки
return false;
}
$json = wp_remote_retrieve_body($result);
$response = json_decode($json, false);
if ($response->success) return true;
else {
echo $json;
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." СЧЁТЧИК. Сервер вернул ответ неудачи: ".print_r($response, true), 3, BG_COUNTER_LOG );
return false;
}
}
// Установить ВСЕ счетчики проекта
function setAllCounts ($request) {
global $project;
$result = wp_remote_post (BG_COUNTER_STAT_SET, array('body' => $request));
if( is_wp_error( $result ) ) {
echo "<br>".$result->get_error_message(); // сообщение ошибки
echo "<br>".$result->get_error_code(); // ключ ошибки
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." ВСЕ СЧЁТЧИКИ. Ошибка при получении данных с сервера: ".$result->get_error_message(), 3, BG_COUNTER_LOG ); // сообщение ошибки
error_log( " " .$result->get_error_code(), 3, BG_COUNTER_LOG ); // ключ ошибки
return false;
}
$json = wp_remote_retrieve_body($result);
$response = json_decode($json, false);
if ($response->success) return true;
else {
echo $json;
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." ВСЕ СЧЁТЧИКИ. Сервер вернул ответ неудачи: ".print_r($response, true), 3, BG_COUNTER_LOG );
return false;
}
}
/*****************************************************************************************
Отображает разметку текста для отображения кол-ва просмотров
и кол-ва читающих пост пользователей
******************************************************************************************/
function bg_az_counter_views ($type=null, $id=null, $now=null) {
if (is_single() || is_page()) {
if (is_null($id)) {
if (!isset ($post)) $post = get_post();
$id = $post->ID;
}
if (is_null($type)) {
$type='post';
}
}
if (is_null($now)) {
$option = get_option('bg_counter_options');
$now = $option['now'];
}
if (!is_null($type) && !is_null($id)) {
$views = '<i title="Просмотры страницы" class="fa fa-eye"></i> <span class="bg-az-counter-views"></span>';
$users = ' <i title="Сейчас читают страницу" class="fa fa-user-o"></i> <span class="bg-az-counter-now"></span>';
$quote = '<span class="bg-az-counter" data-type="'.$type.'" data-ID="'.$id.'">'.$views.($now?$users:'').'</span>';
return $quote;
} else return "";
}
/*****************************************************************************************
Шорт-коды
Функции обработки шорт-кодов
******************************************************************************************/
// Регистрируем шорт-код bg_counter
add_shortcode( 'bg_counter', 'bg_counter_shortcode' );
// Регистрируем шорт-код bg_counter_top_posts
add_shortcode( 'bg_counter_top_posts', 'bg_counter_top_posts_shortcode' );
// [bg_counter type='post' id='1234' now='true']
// Выводит на экран разметку счетчика
function bg_counter_shortcode( $atts ) {
global $post;
extract( shortcode_atts( array(
'type' => null,
'id' => null,
'now' => null
), $atts ) );
$quote = bg_az_counter_views ($type, $id, $now);
return "{$quote}";
}
// [bg_counter_top_posts limit='10']
// Выводит на экран список популярных постов
function bg_counter_top_posts_shortcode( $atts ) {
global $post;
extract( shortcode_atts( array(
'limit' => '10',
'number' => false
), $atts ) );
$quote = getPopularPosts ($limit, 0, (bool)$number);
return "{$quote}";
}
// Запускаем счетчик посещений
include_once ("inc/counter.php");
// Запускаем голосование
include_once ("inc/rating.php");
/* Виджеты Популярные записи
и Сейчас на сайте*/
.widget-item .bg-az-top-posts {
margin: 5px;
padding: 0;
......@@ -37,3 +39,51 @@
i.fa-user-o:before {
margin-left: 1em;
}
/* Рейтинг */
.bg_counter_rating {
position: relative;
padding:0px;
margin:0px;
}
#bg_counter_rate_box {
box-sizing:border-box;
padding:0px;
margin:0px;
}
#bg_counter_rate_box * {
box-sizing:border-box;
padding:0px; margin:0px;
}
#bg_counter_rate_box li {
float:left;
width:20px;
height:20px;
margin-right:3px;
list-style:none;
cursor:defult;
background-image:url(stars.png);
background-size:20px auto;
background-position:0px 20px;
}
#bg_counter_rate_box li::before {
display: none;
}
#bg_counter_popup_help {
position: absolute;
padding: 2px 10px;
margin: 0px;
left: 0px;
bottom: 24px;
min-width: 115px;
z-index: 100;
font-size: 16px;
background-color: rgba(250, 248, 241, 0.9);
color: #8A5536;
display: none;
font-family: Arial;
text-align: center;
border: 1px solid #A6801E;
border-radius: 3px;
box-shadow: 0 0 5px rgba(0,0,0,0.5);
}
<?php
/*****************************************************************************************
GET /rating/<path>
Рейтинг. Возвращает непосредственных потомков, упорядоченных по убыванию
value.
Доступные параметры:
limit - ограничение на количество возвращаемых потомков. По умолчанию: 100
offset - сколько элементов в начале пропустить. По умолчанию: 0
limit/offset работают по такому же принципу, как и в SQL.
Пример запроса:
GET /rating/project/test/author/1?limit=5&offset=3
Пример ответа:
{
"success":true,
"data":[
{"id":"6","type":"book","value":11},
{"id":"7","type":"book","value":7},
{"id":"5","type":"book","value":1},
{"id":"4","type":"book","value":1},
{"id":"3","type":"book","value":1}
]
}
Если счётчик не существует, возвращает пустой массив потомков.
******************************************************************************************/
function getPopularPosts ($limit, $offset=0, $number=false) {
global $project;
$option = get_option('bg_counter_options');
$result = wp_remote_get (BG_COUNTER_STAT_RATING.$project."?limit=".$limit."&offset=".$offset."&type=post");
if( is_wp_error( $result ) ) {
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." RATING (top posts). Ошибка при получении данных с сервера: ".$result->get_error_message(), 3, BG_COUNTER_LOG ); // сообщение ошибки
error_log( " " .$result->get_error_code(), 3, BG_COUNTER_LOG ); // ключ ошибки
return false;
}
if (($code = wp_remote_retrieve_response_code( $result )) != 200) {
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." RATING (top posts). Сервер вернул код ошибки: ".$code, 3, BG_COUNTER_LOG ); // сообщение ошибки
error_log( " " .wp_remote_retrieve_response_message( $result ), 3, BG_COUNTER_LOG ); // ключ ошибки
return false;
}
$json = wp_remote_retrieve_body($result);
$response = json_decode($json, false);
if ($response->success == true){
$the_key='getPopularPosts_key';
if(false===($quote=get_transient($the_key))) {
if ($number) $quote = '<ol class="bg-az-top-posts">'. PHP_EOL;
else $quote = '<ul class="bg-az-top-posts">'. PHP_EOL;
foreach ($response->data as $p) {
if ($p->type!='post') continue;
$id = intval($p->id);
if (!$id) continue;
$post = get_post($id);
if (!$post) continue;
$title = $post->post_title;
$link = '<a href="'. get_permalink($post).'" title="'.$title.'" data-ID="'.$p->id.'" data-type="'.$p->type.'" data-value="'.$p->value.'" data-status="'.$post->post_status.'">'.$title.'</a>';
$quote .= '<li>'.$link.' - <span class="bg-az-count">'.bg_counter_number_format($p->value).'</span></li>'. PHP_EOL;
}
if ($number) $quote .= '</ol>'. PHP_EOL;
else $quote .= '</ul>'. PHP_EOL;
set_transient( $the_key, $quote, $option['period'] );
}
return $quote;
} else {
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." RATING (top posts). Сервер вернул ответ неудачи:\n".$json, 3, BG_COUNTER_LOG );
return false;
}
}
/*****************************************************************************************
POST /set-counter/<path>
Задаёт значение счётчика и создаёт его, если счётчик не существовал.
Предназначено для импорта данных и должно быть закрыто от внешних клиентов.
Пример запроса:
POST /set-counter/project/test/author/1/book/3
Тело: {"counter": 3}
Пример ответа:
{"success": true}
******************************************************************************************/
// Установить 1 счетчик
function setCount ($path, $counter) {
global $project;
$result = wp_remote_post (BG_COUNTER_STAT_SET.$project.$path, array('body' => '{"counter": '.$counter.'}'));
if( is_wp_error( $result ) ) {
echo "<br>".$result->get_error_message(); // сообщение ошибки
echo "<br>".$result->get_error_code(); // ключ ошибки
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." SET-COUNTER. Ошибка при получении данных с сервера: ".$result->get_error_message(), 3, BG_COUNTER_LOG ); // сообщение ошибки
error_log( " " .$result->get_error_code(), 3, BG_COUNTER_LOG ); // ключ ошибки
return false;
}
$json = wp_remote_retrieve_body($result);
$response = json_decode($json, false);
if ($response->success) return true;
else {
echo $json;
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." SET-COUNTER. Сервер вернул ответ неудачи:\n".$json, 3, BG_COUNTER_LOG );
return false;
}
}
// Установить ВСЕ счетчики проекта
function setAllCounts ($request) {
global $project;
$result = wp_remote_post (BG_COUNTER_STAT_SET, array('body' => $request));
if( is_wp_error( $result ) ) {
echo "<br>".$result->get_error_message(); // сообщение ошибки
echo "<br>".$result->get_error_code(); // ключ ошибки
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." SET-COUNTER (all). Ошибка при получении данных с сервера: ".$result->get_error_message(), 3, BG_COUNTER_LOG ); // сообщение ошибки
error_log( " " .$result->get_error_code(), 3, BG_COUNTER_LOG ); // ключ ошибки
return false;
}
$json = wp_remote_retrieve_body($result);
$response = json_decode($json, false);
if ($response->success) return true;
else {
echo $json;
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." SET-COUNTER (all). Сервер вернул ответ неудачи:\n".$json, 3, BG_COUNTER_LOG );
return false;
}
}
/*****************************************************************************************
Отображает разметку текста для отображения кол-ва просмотров
и кол-ва читающих пост пользователей
******************************************************************************************/
function bg_az_counter_views ($type=null, $id=null, $now=null) {
if (is_single() || is_page()) {
if (is_null($id)) {
if (!isset ($post)) $post = get_post();
$id = $post->ID;
}
if (is_null($type)) {
$type='post';
}
}
if (is_null($now)) {
$option = get_option('bg_counter_options');
$now = $option['now'];
}
if (!is_null($type) && !is_null($id)) {
$views = '<i title="Просмотры страницы" class="fa fa-eye"></i> <span class="bg-az-counter-views"></span>';
$users = ' <i title="Сейчас читают страницу" class="fa fa-user-o"></i> <span class="bg-az-counter-now"></span>';
$quote = '<span class="bg-az-counter" data-type="'.$type.'" data-ID="'.$id.'">'.$views.($now?$users:'').'</span>';
return $quote;
} else return "";
}
/*****************************************************************************************
Шорт-коды
Функции обработки шорт-кодов
******************************************************************************************/
// Регистрируем шорт-код bg_counter
add_shortcode( 'bg_counter', 'bg_counter_shortcode' );
// Регистрируем шорт-код bg_counter_top_posts
add_shortcode( 'bg_counter_top_posts', 'bg_counter_top_posts_shortcode' );
// [bg_counter type='post' id='1234' now='true']
// Выводит на экран разметку счетчика
function bg_counter_shortcode( $atts ) {
global $post;
extract( shortcode_atts( array(
'type' => null,
'id' => null,
'now' => null
), $atts ) );
$quote = bg_az_counter_views ($type, $id, $now);
return "{$quote}";
}
// [bg_counter_top_posts limit='10']
// Выводит на экран список популярных постов
function bg_counter_top_posts_shortcode( $atts ) {
global $post;
extract( shortcode_atts( array(
'limit' => '10',
'number' => false
), $atts ) );
$quote = getPopularPosts ($limit, 0, (bool)$number);
return "{$quote}";
}
function bg_counter_number_format ($num) {
$num = floatval ($num);
if ($num > 1000000000.0) {
$num = round($num/1000000000.0, 1)." млрд.";
} elseif ($num > 1000000.0) {
$num = round($num/1000000.0, 1)." млн.";
} elseif ($num > 10000.0) {
$num = round($num/1000.0, 1)." тыс.";
} else {
$num = number_format($num, 0, ',', '&nbsp;');
}
return $num;
}
......@@ -3,8 +3,78 @@
//delete_option('bg_pvc_loaded'); // - " - из Post Views Counter
//delete_option('bg_wppp_loaded'); // - " - из WP Popular Posts
//delete_option('bg_wppm_loaded'); // - " - из произвольных полей "views"
//delete_option('bg_bgar_loaded'); // - " - из плагина Bg Az-Rating
/*****************************************************************************************
Получить данные из плагина WP Popular Posts
и отправить на сервер
******************************************************************************************/
function bg_counter_getBgAzRating() {
global $project;
ini_set('memory_limit', '1024M');
// Список типов записей имеющих страницу во форонте
$post_types = get_post_types( [ 'publicly_queryable'=>1 ] );
$post_types['page'] = 'page'; // встроенный тип не имеет publicly_queryable
unset( $post_types['attachment'] ); // удалим attachment
$posts = get_posts( array(
'numberposts' => -1,
'post_type' => $post_types,
'post_status' =>'publish',
'suppress_filters' => true, // подавление работы фильтров изменения SQL запроса
) );
// Формируем запрос
$i = 0;
$data = array();
$point = array();
foreach( $posts as $post ){
$url = site_url();
$url = str_replace ( wp_parse_url( $url, PHP_URL_PATH ), '', $url);
$page = get_permalink( $post );
$page = str_replace ($url, '', $page);
$point = bg_counter_get_rating($page);
if ($point['votes'] > 0) {
$point['path'] = $project.'/post/'.$post->ID;
$data[] = $point;
$i++;
}
}
wp_reset_postdata(); // сброс
$json = json_encode($data, JSON_UNESCAPED_SLASHES);
echo $json."<br>";
// Отправить данные на сервер
if (!setAllRatings ($json)) return false;
return $i;
}
// Возвращает json массив для текущей страницы
function bg_counter_get_rating($page) {
global $wpdb;
$page_hash = md5($page);
$rtmp = $wpdb->get_row("SELECT * FROM _rating WHERE hesh = '".$page_hash."'", ARRAY_A) ;
if ( $rtmp && $rtmp['rnum'] ) { // Если запись в БД для данной страницы существует, обрабатываем данные
$rating_json['path'] ='';
$rating_json['votes'] = $rtmp['rnum'];
$rating_json['ratings'] = $rtmp['rsum'];
} else {
$rating_json['path'] ='';
$rating_json['votes'] = 0;
$rating_json['ratings'] = 0;
}
return $rating_json;
}
/*****************************************************************************************
Получить данные из произвольного поля views
и отправить на сервер
......@@ -107,13 +177,13 @@ function bg_counter_getPostViewsCounter() {
и отправить на сервер
******************************************************************************************/
function bg_counter_sendArchiveData() {
function bg_counter_sendCounterArchiveData() {
global $project;
// Получить данные из файла архива
$json = file_get_contents ( ABSPATH.BG_COUNTER_ARCHIVE);
$json = file_get_contents ( ABSPATH.BG_COUNTER_ARCHIVE_COUNTER);
if (!$json) {
echo "<br>" ."Ошибка чтения файла: ".BG_COUNTER_ARCHIVE;
echo "<br>" ."Ошибка чтения файла: ".BG_COUNTER_ARCHIVE_COUNTER;
return false;
}
$old_data = json_decode($json, true);
......@@ -135,11 +205,42 @@ function bg_counter_sendArchiveData() {
return $i;
}
function bg_counter_sendRatingArchiveData() {
global $project;
// Получить данные из файла архива
$json = file_get_contents ( ABSPATH.BG_COUNTER_ARCHIVE_RATING);
if (!$json) {
echo "<br>" ."Ошибка чтения файла: ".BG_COUNTER_ARCHIVE_RATING;
return false;
}
$old_data = json_decode($json, true);
// Формируем запрос
$i = 0;
$data = array();
$point = array();
foreach ($old_data as $row) {
$point['path'] = $project.'/'.$row['type'].'/'.$row['id'];
$point['votes'] = $row['votes'];
$point['ratings'] = round ($row['score']*$row['votes']);
$data[] = $point;
$i++;
}
$json = json_encode($data, JSON_UNESCAPED_SLASHES);
echo $json."<br>";
// Отправить данные на сервер
if (!setAllRatings ($json)) return false;
return $i;
}
/*****************************************************************************************
Получить данные с сервера
и сохранить их в файле
******************************************************************************************/
/***** Счетчик посетителей *****/
function bg_counter_saveStatictics() {
global $project;
......@@ -152,15 +253,15 @@ function bg_counter_saveStatictics() {
// Получить данные с сервера
while ($count >= $limit) {
$result = wp_remote_get (BG_COUNTER_STAT_RAITING.$project."?limit=".$limit."&offset=".$offset."&type=post");
$result = wp_remote_get (BG_COUNTER_STAT_RATING.$project."?limit=".$limit."&offset=".$offset."&type=post");
if( is_wp_error( $result ) ) {
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." АРХИВ. Ошибка при получении данных с сервера: ".$result->get_error_message(), 3, BG_COUNTER_LOG ); // сообщение ошибки
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." АРХИВ ПОСЕТИТЕЛЕЙ. Ошибка при получении данных с сервера: ".$result->get_error_message(), 3, BG_COUNTER_LOG ); // сообщение ошибки
error_log( " " .$result->get_error_code(), 3, BG_COUNTER_LOG ); // ключ ошибки
return false;
}
if (($code = wp_remote_retrieve_response_code( $result )) != 200) {
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." АРХИВ. Сервер вернул код ошибки: ".$code, 3, BG_COUNTER_LOG ); // сообщение ошибки
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." АРХИВ ПОСЕТИТЕЛЕЙ. Сервер вернул код ошибки: ".$code, 3, BG_COUNTER_LOG ); // сообщение ошибки
error_log( " " .wp_remote_retrieve_response_message( $result ), 3, BG_COUNTER_LOG ); // ключ ошибки
return false;
}
......@@ -168,7 +269,7 @@ function bg_counter_saveStatictics() {
$json = wp_remote_retrieve_body($result);
$response = json_decode($json, false);
if (!$response->success) {
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." АРХИВ. Сервер вернул ответ неудачи: ".print_r($response, true), 3, BG_COUNTER_LOG );
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." АРХИВ ПОСЕТИТЕЛЕЙ. Сервер вернул ответ неудачи:\n".$json, 3, BG_COUNTER_LOG );
return false;
}
$count = count($response->data);
......@@ -181,13 +282,13 @@ function bg_counter_saveStatictics() {
if ($status != 'publish') {
if ($row->value) {
$defect = " ".$row->id." ".$row->type." ".$row->value." ".$status;
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." АРХИВ. Неверный статус записи: ".$defect, 3, BG_COUNTER_LOG );
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." АРХИВ ПОСЕТИТЕЛЕЙ. Неверный статус записи: ".$defect, 3, BG_COUNTER_LOG );
// Обнуляем счетчик в ошибочной записи
$row->value = 0;
// и отправляем нулевое значение на сервер для удаления
$path = '/'.$row->type.'/'.$row->id;
if (!setCount ($path, 0)) {
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." АРХИВ. Не удалось обнулить запись: ".$path, 3, BG_COUNTER_LOG );
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." АРХИВ ПОСЕТИТЕЛЕЙ. Не удалось обнулить запись: ".$path, 3, BG_COUNTER_LOG );
}
}
}
......@@ -204,10 +305,86 @@ function bg_counter_saveStatictics() {
}
$count = count($data);
$json = json_encode($data, JSON_UNESCAPED_SLASHES);
if (!$json) error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." АРХИВ. Ошибка преобразования в json.", 3, BG_COUNTER_LOG );
if (!$json) error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." АРХИВ ПОСЕТИТЕЛЕЙ. Ошибка преобразования в json.", 3, BG_COUNTER_LOG );
if (file_put_contents ( ABSPATH.BG_COUNTER_ARCHIVE, $json ) === false) {
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." АРХИВ. Ошибка записи в файл: ".BG_COUNTER_ARCHIVE, 3, BG_COUNTER_LOG );
if (file_put_contents ( ABSPATH.BG_COUNTER_ARCHIVE_COUNTER, $json ) === false) {
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." АРХИВ ПОСЕТИТЕЛЕЙ. Ошибка записи в файл: ".BG_COUNTER_ARCHIVE_COUNTER, 3, BG_COUNTER_LOG );
return false;
}
return ($count); // Количество записей для данного проекта
}
/***** Результаты голосований *****/
function bg_counter_saveVotes() {
global $project;
ini_set('memory_limit', '1024M');
$limit = 100;
$offset = 0;
$count = $limit;
$data = array();
// Получить данные с сервера
while ($count >= $limit) {
$result = wp_remote_get (BG_COUNTER_STAT_SCORELIST.$project."?limit=".$limit."&offset=".$offset."&type=post");
if( is_wp_error( $result ) ) {
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." АРХИВ ГОЛОСОВАНИЙ. Ошибка при получении данных с сервера: ".$result->get_error_message(), 3, BG_COUNTER_LOG ); // сообщение ошибки
error_log( " " .$result->get_error_code(), 3, BG_COUNTER_LOG ); // ключ ошибки
return false;
}
if (($code = wp_remote_retrieve_response_code( $result )) != 200) {
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." АРХИВ ГОЛОСОВАНИЙ. Сервер вернул код ошибки: ".$code, 3, BG_COUNTER_LOG ); // сообщение ошибки
error_log( " " .wp_remote_retrieve_response_message( $result ), 3, BG_COUNTER_LOG ); // ключ ошибки
return false;
}
$json = wp_remote_retrieve_body($result);
$response = json_decode($json, false);
if (!$response->success) {
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." АРХИВ ГОЛОСОВАНИЙ. Сервер вернул ответ неудачи:\n".$json, 3, BG_COUNTER_LOG );
return false;
}
$count = count($response->data);
$i=0;
if ($count) {
// Верификация и очистка записей
foreach ($response->data as &$row) {
$status = verify_post ($row->id);
if ($status != 'publish') {
if ($row->votes) {
$defect = " ".$row->id." ".$row->type." ".$row->score." ".$row->votes." ".$status;
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." АРХИВ ГОЛОСОВАНИЙ. Неверный статус записи: ".$defect, 3, BG_COUNTER_LOG );
// Обнуляем счетчик в ошибочной записи
$row->votes = 0;
$row->score = 0;
// и отправляем нулевое значение на сервер для удаления
$path = '/'.$row->type.'/'.$row->id;
if (!setRating ($path, '{"votes": 0, "ratings": 0}')) {
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." АРХИВ ГОЛОСОВАНИЙ. Не удалось обнулить запись: ".$path, 3, BG_COUNTER_LOG );
}
}
}
// Удаляем записи с нулевыми значениями из сохраняемого массива
if ($row->votes == 0) unset($response->data[$i]);
$i++;
}
unset($row);
$data = array_merge($data, $response->data);
}
$offset += $limit;
}
$count = count($data);
$json = json_encode($data, JSON_UNESCAPED_SLASHES);
if (!$json) error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." АРХИВ ГОЛОСОВАНИЙ. Ошибка преобразования в json.", 3, BG_COUNTER_LOG );
if (file_put_contents ( ABSPATH.BG_COUNTER_ARCHIVE_RATING, $json ) === false) {
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." АРХИВ ГОЛОСОВАНИЙ. Ошибка записи в файл: ".BG_COUNTER_ARCHIVE_RATING, 3, BG_COUNTER_LOG );
return false;
}
......@@ -250,9 +427,14 @@ add_action( 'bg_counter_stack_cron_action', 'bg_counter_daily_action' );
function bg_counter_daily_action () {
date_default_timezone_set (get_option('timezone_string'));
// Сохраняем архив результатов
// Сохраняем архивы результатов
$result = bg_counter_saveStatictics();
if ($result !== false) update_option( 'bg_archive_status', "<div class='notice notice-info'><p><b>".date("Y-m-d H:i:s", time())."</b> сохранено <b>". $result ."</b> записей в файле архива статистики: <code>". BG_COUNTER_ARCHIVE ."</code></p></div>" );
else update_option( 'bg_archive_status', "<div class='notice notice-error'><p><b>".date("Y-m-d H:i:s", time())."</b> Ошибка при сохранении данных статистки. См. журнал ошибок: <code>". BG_COUNTER_LOG ."</code></p></div>" );
}
if ($result !== false) $message = "<div class='notice notice-success'><p><b>".date("Y-m-d H:i:s", time())."</b> сохранено <b>". $result ."</b> записей в файле архива статистики: <code>". BG_COUNTER_ARCHIVE_COUNTER ."</code></p></div>";
else $message = "<div class='notice notice-error'><p><b>".date("Y-m-d H:i:s", time())."</b> Ошибка при сохранении данных статистки. См. журнал ошибок: <code>". BG_COUNTER_LOG ."</code></p></div>";
$result = bg_counter_saveVotes();
if ($result !== false) $message .= "<div class='notice notice-success'><p><b>".date("Y-m-d H:i:s", time())."</b> сохранено <b>". $result ."</b> записей в файле архива статистики: <code>". BG_COUNTER_ARCHIVE_RATING ."</code></p></div>";
else $message .= "<div class='notice notice-error'><p><b>".date("Y-m-d H:i:s", time())."</b> Ошибка при сохранении данных статистки. См. журнал ошибок: <code>". BG_COUNTER_LOG ."</code></p></div>";
update_option( 'bg_archive_status', $message);
}
......@@ -4,10 +4,11 @@
*******************************************************************************************/
// Начальные значения
add_option('bg_counter_options', array('period'=>DAY_IN_SECONDS, 'now'=>0, 'debug'=>0, 'archive'=>0, 'pvc'=>0, 'wppp'=>0, 'wppm'=>0));
add_option('bg_counter_options', array('period'=>DAY_IN_SECONDS, 'now'=>0, 'title'=>'', 'author'=>'', 'debug'=>0, 'archive'=>0, 'pvc'=>0, 'wppp'=>0, 'wppm'=>0, 'bgar'=>0));
add_option('bg_pvc_loaded', '');
add_option('bg_wppp_loaded', '');
add_option('bg_wppm_loaded', '');
add_option('bg_bgar_loaded', '');
$val = get_option('bg_counter_options');
if (!isset($val['period'])) {
$val['period'] = DAY_IN_SECONDS;
......@@ -16,6 +17,12 @@ if (!isset($val['period'])) {
if (!isset($val['now'])) {
$val['now'] = 0;
}
if (!isset($val['title'])) {
$val['title'] = "";
}
if (!isset($val['author'])) {
$val['author'] = "Редакция портала Азбука веры";
}
if (!isset($val['debug'])) {
$val['debug'] = 0;
}
......@@ -31,6 +38,9 @@ if (!isset($val['wppp'])) {
if (!isset($val['wppm'])) {
$val['wppm'] = 0;
}
if (!isset($val['bgar'])) {
$val['bgar'] = 0;
}
update_option( 'bg_counter_options', $val );
add_action('admin_menu', 'bg_counter_add_plugin_page');
......@@ -46,6 +56,8 @@ function bg_counter_options_page_output(){
$pvc_loaded = get_option('bg_pvc_loaded');
$wppp_loaded = get_option('bg_wppp_loaded');
$wppm_loaded = get_option('bg_wppm_loaded');
$bgar_loaded = get_option('bg_bgar_loaded');
// Post Views Counter
if ((isset($pvc_loaded) && $pvc_loaded != 'on') && (isset($val['pvc']) && $val['pvc']) ) {
echo '<h2>Загрузка данных из Post Views Counter:</h2>';
$bg_from_pvc_result = bg_counter_getPostViewsCounter ();
......@@ -58,6 +70,7 @@ function bg_counter_options_page_output(){
echo "<br><div class='notice notice-success'><p>Все данные ($bg_from_pvc_result) из плагина <b>Post Views Counter</b> перенесены на сервер.</p></div>";
}
submit_button( "Продолжить...", "", "", true, "onclick='location.reload();'" );
// WP Popular Posts
}else if ((isset($wppp_loaded) && $wppp_loaded != 'on') && (isset($val['wppp']) && $val['wppp']) ) {
echo '<h2>Загрузка данных из WP Popular Posts:</h2>';
$bg_from_wppp_result = bg_counter_getWPPopularPosts ();
......@@ -70,6 +83,7 @@ function bg_counter_options_page_output(){
echo "<br><div class='notice notice-success'><p>Все данные ($bg_from_wppp_result) из плагина <b>WP Popular Posts</b> перенесены на сервер.</p></div>";
}
submit_button( "Продолжить...", "", "", true, "onclick='location.reload();'" );
// WP post meta "views"
} else if ((isset($wppm_loaded) && $wppm_loaded != 'on') && (isset($val['wppm']) && $val['wppm']) ) {
echo '<h2>Загрузка данных из WP post meta "views":</h2>';
$bg_from_wppm_result = bg_counter_getWPPostMeta ();
......@@ -82,21 +96,41 @@ function bg_counter_options_page_output(){
echo "<br><div class='notice notice-success'><p>Все данные ($bg_from_wppm_result) из произвольных полей <b>views</b> постов перенесены на сервер.</p></div>";
}
submit_button( "Продолжить...", "", "", true, "onclick='location.reload();'" );
} else if ((isset($val['archive']) && $val['archive']) ) {
echo '<h2>Загрузка данных из архива '.BG_COUNTER_ARCHIVE.':</h2>';
$bg_from_archive_result = bg_counter_sendArchiveData ();
$val['archive'] = 0;
// Bg Az-Rating
} else if ((isset($bgar_loaded) && $bgar_loaded != 'on') && (isset($val['bgar']) && $val['bgar']) ) {
echo '<h2>Загрузка данных из Bg Az-Rating:</h2>';
$bg_from_bgar_result = bg_counter_getBgAzRating ();
$val['bgar'] = 0;
update_option( 'bg_counter_options', $val );
if ($bg_from_archive_result === false) {
if ($bg_from_bgar_result === false) {
echo "<br><div class='notice notice-error'><p><b>ОШИБКА</b> при отправке данных на сервер.</p></div>";
} else {
update_option('bg_wppp_loaded','on');
echo "<br><div class='notice notice-success'><p>Все данные ($bg_from_archive_result) из архива <b>".BG_COUNTER_ARCHIVE."</b> перенесены на сервер.</p></div>";
update_option('bg_bgar_loaded','on');
echo "<br><div class='notice notice-success'><p>Все данные ($bg_from_bgar_result) из плагина <b>Bg Az-Rating</b> постов перенесены на сервер.</p></div>";
}
submit_button( "Продолжить...", "", "", true, "onclick='location.reload();'" );
// Архивы
} else if ((isset($val['archive']) && $val['archive']) ) {
echo '<h2>Загрузка данных из архивов '.BG_COUNTER_ARCHIVE_COUNTER.' и '.BG_COUNTER_ARCHIVE_RATING.':</h2>';
$bg_from_archive_result = bg_counter_sendCounterArchiveData ();
if ($bg_from_archive_result === false) {
echo "<br><div class='notice notice-error'><p><b>".BG_COUNTER_ARCHIVE_COUNTER.":</b> <i>ОШИБКА</i> при отправке данных на сервер.</p></div>";
} else {
echo "<br><div class='notice notice-success'><p>Все данные ($bg_from_archive_result) из архива <b>".BG_COUNTER_ARCHIVE_COUNTER."</b> перенесены на сервер.</p></div>";
}
$bg_from_archive_result = bg_counter_sendRatingArchiveData ();
if ($bg_from_archive_result === false) {
echo "<br><div class='notice notice-error'><p><b>".BG_COUNTER_ARCHIVE_RATING.":</b> <i>ОШИБКА</i> при отправке данных на сервер.</p></div>";
} else {
echo "<br><div class='notice notice-success'><p>Все данные ($bg_from_archive_result) из архива <b>".BG_COUNTER_ARCHIVE_RATING."</b> перенесены на сервер.</p></div>";
}
$val['archive'] = 0;
update_option( 'bg_counter_options', $val );
submit_button( "Продолжить...", "", "", true, "onclick='location.reload();'" );
} else {
if ((isset($val['period']) && $val['period'] != get_option('bg_counter_period')) ) {
delete_transient( 'getPopularPostss_key' );
delete_transient( 'getPopularPosts_key' );
delete_transient( 'getPostRating_key' );
update_option( 'bg_counter_period', $val['period'] );
}
$archive_status = get_option('bg_archive_status');
......@@ -105,6 +139,7 @@ function bg_counter_options_page_output(){
?>
<div class="wrap">
<h2><?php echo get_admin_page_title() ?></h2>
<p>Версия <b><?php echo BG_COUNTER_VERSION; ?></b></p>
<form action="options.php" method="POST">
<?php
settings_fields( 'bg_counter_option_group' ); // скрытые защитные поля
......@@ -128,16 +163,19 @@ function bg_counter_settings(){
// параметры: $id, $title, $callback, $page
add_settings_section( 'section_1','Основные параметры', '', 'bg_counter_page' );
add_settings_section( 'section_2', 'Загрузка данных из WP Popular Posts', '', 'bg_counter_loaded' );
add_settings_section( 'section_2', 'Импорт данных', '', 'bg_counter_loaded' );
// параметры: $id, $title, $callback, $page, $section, $args
add_settings_field('bg_counter_period', 'Периодичность обработки данных', 'fill_bg_counter_period', 'bg_counter_page', 'section_1' );
add_settings_field('bg_counter_now', 'Просматривают сейчас', 'fill_bg_counter_now', 'bg_counter_page', 'section_1' );
add_settings_field('bg_counter_title', 'Общее название в сниппете по умолчанию', 'fill_bg_counter_title', 'bg_counter_page', 'section_1' );
add_settings_field('bg_counter_author', 'Общее имя автора в сниппете по умолчанию', 'fill_bg_counter_author', 'bg_counter_page', 'section_1' );
add_settings_field('bg_counter_debug', 'Включить отладку', 'fill_bg_counter_debug', 'bg_counter_page', 'section_1' );
add_settings_field('bg_counter_archive', 'Загрузить данные из архива на сервер', 'fill_bg_counter_sendArchive', 'bg_counter_page', 'section_1' );
add_settings_field('bg_counter_pvc', 'Загрузить данные из Post Views Counter', 'fill_bg_counter_pvc', 'bg_counter_page', 'section_1' );
add_settings_field('bg_counter_wppp', 'Загрузить данные из WP Popular Posts', 'fill_bg_counter_wppp', 'bg_counter_page', 'section_1' );
add_settings_field('bg_counter_wppm', 'Загрузить данные из произвольных полей "views"', 'fill_bg_counter_wppm', 'bg_counter_page', 'section_1' );
add_settings_field('bg_counter_bgar', 'Загрузить данные из Bg Az-Rating', 'fill_bg_counter_bgar', 'bg_counter_page', 'section_1' );
}
......@@ -168,6 +206,26 @@ function fill_bg_counter_now(){
}
## Заполняем опцию 3
function fill_bg_counter_title(){
$val = get_option('bg_counter_options');
$val = $val['title'];
?>
<input type="text" name="bg_counter_options[title]" value="<?php echo esc_attr( $val ) ?>" size="60" /><br>
(если не указано, то по умолчанию название поста)
<?php
}
## Заполняем опцию 4
function fill_bg_counter_author(){
$val = get_option('bg_counter_options');
$val = $val['author'];
?>
<input type="text" name="bg_counter_options[author]" value="<?php echo esc_attr( $val ) ?>" size="60" /><br>
(если не указано, то по умолчанию имя автора в метаполе 'author' поста,<br>если же и метаполе отсутствует, то название сайта)
<?php
}
## Заполняем опцию 5
function fill_bg_counter_debug(){
$val = get_option('bg_counter_options');
$val = $val ? $val['debug'] : null;
......@@ -239,6 +297,21 @@ function fill_bg_counter_wppm(){
}
}
## Заполняем опцию 10
function fill_bg_counter_bgar(){
$val = get_option('bg_counter_options');
$bgar_loaded = get_option('bg_bgar_loaded');
if (isset($bgar_loaded) && $bgar_loaded == 'on'){
echo '<i>Данные из Bg Az-Rating уже загружены на сервер.</i>';
} else {
// Всегда предлагать сохранить не отмеченный
?>
<label><input type="checkbox" name="bg_counter_options[bgar]" value="1" /> отметьте и нажмите кнопку «Сохранить изменения» </label>
<?php
}
}
## Очистка данных
function bg_counter_sanitize_callback( $options ){
// очищаем
......@@ -249,6 +322,12 @@ function bg_counter_sanitize_callback( $options ){
if( $name == 'now' )
$val = intval( $val );
if( $name == 'title' )
$val = strip_tags( $val );
if( $name == 'author' )
$val = strip_tags( $val );
if( $name == 'debug' )
$val = intval( $val );
......@@ -263,6 +342,9 @@ function bg_counter_sanitize_callback( $options ){
if( $name == 'wppm' )
$val = intval( $val );
if( $name == 'bgar' )
$val = intval( $val );
}
return $options;
}
<?php
/*****************************************************************************************
Функции для вывода рейтинга на странице
******************************************************************************************/
/*********************************************************************************
GET /item-score/<path>
Возвращает рейтинг и количество голосов отдельно взятого объекта -
score. Также возвращается флаг, голосовал ли уже данный пользователь.
Пример запроса:
GET /item-score/project/test/author/1
Пример ответа:
{
"success": true,
"data": {
"alreadyVoted":true,
"score": 3.7142857142857144,
"votes": 7
}
}
Если объект не существует, возвращает success: false и data: null.
Важно: если alreadyVoted равно true, то повторная попытка голосования
провалится.
**********************************************************************************/
function bg_az_counter_rating($type, $id) {
global $project;
$option = get_option('bg_counter_options');
if ($option['title']) $page_title = $option['title'];
else $page_title = get_the_title($id);
if ($option['author']) $author = $option['author'];
else {
$author = get_post_meta($id, 'author', true);
if(!$author) $author = get_bloginfo('name');
}
$result = wp_remote_get (BG_COUNTER_STAT_SCORE.$project."/".$type."/".$id);
if( is_wp_error( $result ) ) {
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." ITEM-SCORE. Ошибка при получении данных с сервера: ".$result->get_error_message(), 3, BG_COUNTER_LOG ); // сообщение ошибки
error_log( " " .$result->get_error_code(), 3, BG_COUNTER_LOG ); // ключ ошибки
return false;
}
if (($code = wp_remote_retrieve_response_code( $result )) != 200) {
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." ITEM-SCORE. Сервер вернул код ошибки: ".$code, 3, BG_COUNTER_LOG ); // сообщение ошибки
error_log( " " .wp_remote_retrieve_response_message( $result ), 3, BG_COUNTER_LOG ); // ключ ошибки
return false;
}
$json = wp_remote_retrieve_body($result);
$response = json_decode($json, false);
if (!$response->success) {
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." ITEM-SCORE. Сервер вернул ответ неудачи:\n".$json, 3, BG_COUNTER_LOG );
$score = 0;
$votes = 0;
$alreadyVoted = false;
} else {
$data = $response->data;
$score = number_format((float)$data->score, 1, ',', '');
$votes = $data->votes;
$alreadyVoted = $data->alreadyVoted;
}
$txt_votes = bg_counter_txt_votes($votes);
echo <<<HTML
<div class="bg_counter_rating">
<div><ul id="bg_counter_rate_box">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<span itemscope="" itemtype="http://schema.org/AggregateRating">
<meta itemprop="bestRating" content="5" />
<meta itemprop="worstRating" content="1" />
<meta itemprop="author" content="{$author}" />
<meta itemprop="itemReviewed" content="{$page_title}" />
<meta content="{$score}" itemprop="ratingValue">
<meta content="{$votes}" itemprop="ratingCount">
(<span id="bg_counter_votes">{$votes}</span> <span id="bg_counter_votes_txt">{$txt_votes}</span>:
<span id="bg_counter_score" data-voted="{$alreadyVoted}">{$score}</span> из <span id="bg_counter_rating_max">5</span>)
</span></div>
<div id="bg_counter_popup_help"></div>
</div>
HTML;
}
/*****************************************************************************************
GET /scores-list/<path>
Возвращает непосредственных потомков, упорядоченных по убыванию рейтинга -
score.
Доступные параметры:
limit, offset - аналогично запросу GET /rating/<path>.
Пример запроса:
GET /scores-list/project/test/author/1?limit=3&offset=1
Пример ответа:
{
"success":true,
"data":[
{"id": "4", "type": "book", "score": 4.083333333333333, "votes": 12},
{"id": "1", "type": "book", "score": 4.0625, "votes": 16},
{"id": "2", "type": "book", "score": 4.0588235294117645, "votes": 17}
]
}
Если объект не существует, возвращает пустой массив потомков.
******************************************************************************************/
function getPostRating ($limit, $offset=0, $number=false) {
global $project;
$option = get_option('bg_counter_options');
$result = wp_remote_get (BG_COUNTER_STAT_SCORELIST.$project."?limit=".$limit."&offset=".$offset."&type=post");
if( is_wp_error( $result ) ) {
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." SCORES-LIST. Ошибка при получении данных с сервера: ".$result->get_error_message(), 3, BG_COUNTER_LOG ); // сообщение ошибки
error_log( " " .$result->get_error_code(), 3, BG_COUNTER_LOG ); // ключ ошибки
return false;
}
if (($code = wp_remote_retrieve_response_code( $result )) != 200) {
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." SCORES-LIST. Сервер вернул код ошибки: ".$code, 3, BG_COUNTER_LOG ); // сообщение ошибки
error_log( " " .wp_remote_retrieve_response_message( $result ), 3, BG_COUNTER_LOG ); // ключ ошибки
return false;
}
$json = wp_remote_retrieve_body($result);
$response = json_decode($json, false);
if ($response->success == true){
$the_key='getPostRating_key';
if(false===($quote=get_transient($the_key))) {
if ($number) $quote = '<ol class="bg-az-top-posts">'. PHP_EOL;
else $quote = '<ul class="bg-az-top-posts">'. PHP_EOL;
foreach ($response->data as $p) {
if ($p->type!='post') continue;
$id = intval($p->id);
$votes = intval($p->votes);
$votes = intval($p->votes);
if (!$id) continue;
$post = get_post($id);
if (!$post) continue;
$title = $post->post_title;
$link = '<a href="'. get_permalink($post).'" title="'.$title.'" data-ID="'.$p->id.'" data-type="'.$p->type.'" data-score="'.$p->score.'" data-status="'.$post->post_status.'">'.$title.'</a>';
$txt_votes = bg_counter_txt_votes($votes);
$txt_score = $votes.' '.$txt_votes.': '.number_format((float)$p->score, 1, ',', '').' из 5';
$quote .= '<li>'.$link.' - <span class="bg-az-count">'.$txt_score.'</span></li>'. PHP_EOL;
}
if ($number) $quote .= '</ol>'. PHP_EOL;
else $quote .= '</ul>'. PHP_EOL;
set_transient( $the_key, $quote, $option['period'] );
}
return $quote;
} else {
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." SCORES-LIST. Сервер вернул ответ неудачи:\n".$json, 3, BG_COUNTER_LOG );
return false;
}
}
/*****************************************************************************************
POST /set-rating/<path>
Устанвливает рейтинг для объекта и создаёт его, если объекта не существовал.
Пример запроса:
POST /set-rating/project/test/author/1/book/3
Тело: {"votes": 10, "ratings": 46}
Пример ответа:
{"success": true}
Альтернативная форма запроса для массового импорта:
POST /set-rating с телом:
[
{"path": "/test/1/author/2", "votes": 10, "ratings": 46},
...
]
******************************************************************************************/
// Установить счетчик рейтинга
function setRating ($path, $request) {
global $project;
$result = wp_remote_post (BG_COUNTER_STAT_SET_RATINGS.$project.$path, array('body' => $request));
if( is_wp_error( $result ) ) {
echo "<br>".$result->get_error_message(); // сообщение ошибки
echo "<br>".$result->get_error_code(); // ключ ошибки
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." SET-RATING. Ошибка при получении данных с сервера: ".$result->get_error_message(), 3, BG_COUNTER_LOG ); // сообщение ошибки
error_log( " " .$result->get_error_code(), 3, BG_COUNTER_LOG ); // ключ ошибки
return false;
}
$json = wp_remote_retrieve_body($result);
$response = json_decode($json, false);
if ($response->success) return true;
else {
echo $json;
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." SET-RATING. Сервер вернул ответ неудачи:\n".$json, 3, BG_COUNTER_LOG );
return false;
}
}
// Установить ВСЕ счетчики рейтинга
function setAllRatings ($request) {
global $project;
$result = wp_remote_post (BG_COUNTER_STAT_SET_RATINGS, array('body' => $request));
if( is_wp_error( $result ) ) {
echo "<br>".$result->get_error_message(); // сообщение ошибки
echo "<br>".$result->get_error_code(); // ключ ошибки
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." SET-RATINGS (all). Ошибка при получении данных с сервера: ".$result->get_error_message(), 3, BG_COUNTER_LOG ); // сообщение ошибки
error_log( " " .$result->get_error_code(), 3, BG_COUNTER_LOG ); // ключ ошибки
return false;
}
$json = wp_remote_retrieve_body($result);
$response = json_decode($json, false);
if ($response->success) return true;
else {
echo $json;
error_log( PHP_EOL .date("Y-m-d H:i:s ", time())." SET-RATINGS (all). Сервер вернул ответ неудачи:\n".$json, 3, BG_COUNTER_LOG );
return false;
}
}
/*****************************************************************************************
Шорт-коды
Функции обработки шорт-кода
******************************************************************************************/
// Регистрируем шорт-код bg_az_rating
add_shortcode( 'bg_az_rating', 'bg_az_rating_shortcode' );
// [bg_az_rating]
function bg_az_rating_shortcode( $atts ) {
extract( shortcode_atts( array(
'type' => null,
'id' => null
), $atts ) );
if (is_null($id)) {
$id = get_the_ID();
}
if (is_null($type)) {
$type = 'post';
}
$quote = bg_az_counter_rating($type, $id);
return "{$quote}";
}
// Склоняем слово "голос"
function bg_counter_txt_votes ($votes){
$m = $votes % 10;
$j = $votes % 100;
if($m==0 || $m>=5 || ($j>=10 && $j<=20)) $txt_votes = 'голосов';
else if($m>=2 && $m<=4) $txt_votes = 'голоса';
else $txt_votes = 'голос';
return $txt_votes;
}
......@@ -141,6 +141,74 @@ class bg_counter_OnlineNowWidget extends WP_Widget {
return $instance;
}
}
/*****************************************************************************************
Виджет отображает в сайдбаре
Список популярных постов по результатам голосования
******************************************************************************************/
class bg_counter_PostRatingWidget extends WP_Widget {
// создание виджета
function __construct() {
parent::__construct(
'bg_counter_post_rating_widget',
'Популярные записи', // заголовок виджета
array( 'description' => 'Позволяет вывести записи, отсортированные по количеству голосов.' ) // описание
);
}
// фронтэнд виджета
public function widget( $args, $instance ) {
$title = apply_filters( 'widget_title', $instance['title'] ); // к заголовку применяем фильтр (необязательно)
$posts_per_page = $instance['posts_per_page'];
echo $args['before_widget'];
if ( ! empty( $title ) )
echo $args['before_title'] . $title . $args['after_title'];
$list = getPostRating ($posts_per_page);
if ($list) {
?>
<div class="widget-item">
<div class="widget-inner">
<?php echo $list; ?>
</div>
</div>
<?php
}
echo $args['after_widget'];
}
// бэкэнд виджета
public function form( $instance ) {
if ( isset( $instance[ 'title' ] ) ) {
$title = $instance[ 'title' ];
}
if ( isset( $instance[ 'posts_per_page' ] ) ) {
$posts_per_page = $instance[ 'posts_per_page' ];
}
?>
<p>
<label for="<?php echo $this->get_field_id( 'title' ); ?>">Заголовок</label>
<input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>" />
</p>
<p>
<label for="<?php echo $this->get_field_id( 'posts_per_page' ); ?>">Количество записей:</label>
<input id="<?php echo $this->get_field_id( 'posts_per_page' ); ?>" name="<?php echo $this->get_field_name( 'posts_per_page' ); ?>" type="text" value="<?php echo ($posts_per_page) ? esc_attr( $posts_per_page ) : '5'; ?>" size="3" />
</p>
<?php
}
// сохранение настроек виджета
public function update( $new_instance, $old_instance ) {
$instance = array();
$instance['title'] = ( ! empty( $new_instance['title'] ) ) ? strip_tags( $new_instance['title'] ) : '';
$instance['posts_per_page'] = ( is_numeric( $new_instance['posts_per_page'] ) ) ? $new_instance['posts_per_page'] : '5'; // по умолчанию выводятся 5 постов
return $instance;
}
}
/*****************************************************************************************
Регистрация виджетов
......@@ -149,5 +217,6 @@ class bg_counter_OnlineNowWidget extends WP_Widget {
function bg_counter_widgets_load() {
register_widget( 'bg_counter_TopPostsWidget' );
register_widget( 'bg_counter_OnlineNowWidget' );
register_widget( 'bg_counter_PostRatingWidget' );
}
add_action( 'widgets_init', 'bg_counter_widgets_load' );
\ No newline at end of file
......@@ -12,13 +12,13 @@ jQuery( document ).ready(function() {
if (bg_counter.debug) console.log(" Соединение установлено. "+request);
GetAllCounters();
};
}
GetAllCounters();
} else GetAllCounters();
});
/*********************************************************************************
POST /counters/<path>
Увеличивает счётчик на единицу (и создаёт его, если он не существует).
Тело запроса пустое.
......@@ -32,11 +32,11 @@ jQuery( document ).ready(function() {
"success":true,
"data":{
"created": false,
"now": 3,
"value": 35
}
}
В ответе параметр created говорит, существовал ли счётчик до этого.
**********************************************************************************/
function SendOnce(type, id) {
......@@ -51,7 +51,7 @@ function SendOnce(type, id) {
if (response.success) {
// Здесь надо будет добавить вывод данных на экран
if (bg_counter.debug) console.log(JSON.stringify(response.data));
setViewCount (id, addDelimiter(response.data.value));
setViewCount (type, id, bg_counter_number_format(response.data.value), (response.data.now+1));
} else {
if (bg_counter.debug) console.log('POST REQUEST: '+request+' ERROR: '+response.error);
}
......@@ -100,8 +100,8 @@ function GetAllCounters() {
if (response.success) {
if (bg_counter.debug) console.log('GET REQUEST: '+request);
if (bg_counter.debug) console.log(JSON.stringify(response.data));
el.find('span.bg-az-counter-views').text(addDelimiter(response.data.total));
el.find('span.bg-az-counter-now').text(addDelimiter(response.data.now));
el.find('span.bg-az-counter-views').text(bg_counter_number_format(response.data.total));
el.find('span.bg-az-counter-now').text(bg_counter_number_format(response.data.now));
} else {
if (bg_counter.debug) console.log('GET REQUEST: '+request+' ERROR '+xhr.status+': '+response.error);
el.find('span.bg-az-counter-views').text('0');
......@@ -149,3 +149,19 @@ function addDelimiter(nStr, dlm='\xa0') {
}
return x1 + x2;
}
function bg_counter_number_format (num) {
num = parseFloat (num);
if (num > 1000000000.0) {
num = num/1000000000;
num = num.toFixed(1)+" млрд.";
} else if (num > 1000000.0) {
num = num/1000000;
num = num.toFixed(1)+" млн.";
} else if (num > 10000.0) {
num = num/1000;
num = num.toFixed(1)+" тыс.";
} else {
num = addDelimiter(num);
}
return num;
}
var start_rate_index, rating_voted;
var options={};
options.expires=60*60*24; // Кука на сутки
options.path=window.location.pathname; // Текущий путь
jQuery( document ).ready(function() {
if (!bg_counter.ID) return;
// start_rate_index = Math.round(parseFloat(jQuery( "#bg_counter_score" ).html()));
// var price = ["очень плохо", "плохо", "удовлетворительно", "хорошо", "отлично"];
start_rate_index = parseFloat(jQuery( "#bg_counter_score" ).html());
rating_voted = (jQuery( "#bg_counter_score" ).attr("data-voted")=='true')?true:false;
iniRatingState(start_rate_index, rating_voted);
getRate(bg_counter.type, bg_counter.ID);
jQuery( "#bg_counter_rate_box li" ).mouseover(function() {
if(!rating_voted){
var index = jQuery( this ).index();
iniRatingState(index+1, rating_voted);
jQuery('#bg_counter_popup_help').text(bg_counter.price[index]);
// jQuery('#bg_counter_popup_help').css('width', '110px');
} else {
jQuery('#bg_counter_popup_help').text(bg_counter.voted);
// jQuery('#bg_counter_popup_help').css('width', '260px');
}
jQuery('#bg_counter_popup_help').show();
});
jQuery( "#bg_counter_rate_box" ).mouseout(function() {
if(!rating_voted){
iniRatingState(start_rate_index, rating_voted);
}
jQuery('#bg_counter_popup_help').hide();
});
jQuery( "#bg_counter_rate_box li" ).click(function() {
if(!rating_voted){
rating_voted = true;
jQuery( "#bg_counter_rate_box li" ).css('cursor', 'default');
var sindex = jQuery( this ).index()+1;
sendRate(bg_counter.type, bg_counter.ID, sindex);
}
});
});
function iniRatingState(sindex, voted){
if(!voted) jQuery( "#bg_counter_rate_box li" ).css('cursor', 'pointer');
else jQuery( "#bg_counter_rate_box li" ).css('cursor', 'default');
star = parseInt(jQuery( "#bg_counter_rate_box li" ).css('height')); /* высота звездочки */
jQuery( "#bg_counter_rate_box li" ).css('background-position', '0px '+star+'px');
jQuery( "#bg_counter_rate_box li" ).each(function( index ) {
n=sindex-sindex%1;
if(index < n){
jQuery(this).css('background-position', '0px '+5*star+'px');
}
else if (sindex-index > 0) {
p=star*(Math.round(4*(sindex-index))+1);
jQuery(this).css('background-position', '0px '+p+'px');
}
});
}
/*********************************************************************************
GET /item-score/<path>
Возвращает рейтинг и количество голосов отдельно взятого объекта -
score. Также возвращается флаг, голосовал ли уже данный пользователь.
Пример запроса:
GET /item-score/project/test/author/1
Пример ответа:
{
"success": true,
"data": {
"alreadyVoted":true,
"score": 3.7142857142857144,
"votes": 7
}
}
Если объект не существует, возвращает success: false и data: null.
Важно: если alreadyVoted равно true, то повторная попытка голосования
провалится.
**********************************************************************************/
function getRate(type, id) {
var request = bg_counter.scoreurl+bg_counter.project+"/"+type+"/"+id;
var xhr = new XMLHttpRequest();
xhr.open("GET", request, true);
if (bg_counter.debug) console.log('GET REQUEST: '+request);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if (xhr.responseText) {
var response = JSON.parse(xhr.responseText);
if (response.success) {
// Вывод данных на экран
if (bg_counter.debug) console.log(JSON.stringify(response.data));
m = response.data.votes % 10;
j = response.data.votes % 100;
if(m==0 || m>=5 || (j>=10 && j<=20)) txt_votes = bg_counter.votes5;
else if(m>=2 && m<=4) txt_votes = bg_counter.votes2;
else txt_votes = bg_counter.vote1;
start_rate_index = parseFloat(response.data.score).toFixed(1);
jQuery('#bg_counter_votes').html(response.data.votes);
jQuery('#bg_counter_votes_txt').html(txt_votes);
jQuery('#bg_counter_score').html(start_rate_index);
iniRatingState(start_rate_index, response.data.alreadyVoted);
} else {
if (bg_counter.debug) console.log('GET REQUEST: '+request+' ERROR: '+response.error);
jQuery('#bg_counter_votes').html('0');
jQuery('#bg_counter_votes_txt').html(bg_counter.votes5);
jQuery('#bg_counter_score').html('0');
iniRatingState(0, false);
}
}
}
}
xhr.send();
}
/*********************************************************************************
POST /rate/<path>
Увеличивает сумму оценок объекта на указанную величину (от 1 до 5) и количество
голосов на 1.
Возвращает новый рейтинг и количество голосов. Рейтинг рассчитывается по формуле:
новый рейтинг = сумма оценок / количество голосов;
Пример запроса:
POST /rate/project/test/author/1/book/3
Тело: {"rating": 4}
Пример ответа:
{
"success": true,
"data": {"score": 4.0625, "votes": 16}
}
**********************************************************************************/
function sendRate(type, id, number) {
var request = bg_counter.rateurl+bg_counter.project+"/"+type+"/"+id;
var xhr = new XMLHttpRequest();
xhr.open("POST", request, true);
if (bg_counter.debug) console.log('POST REQUEST: '+request);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if (xhr.responseText) {
var response = JSON.parse(xhr.responseText);
if (response.success) {
// Вывод данных на экран
if (bg_counter.debug) console.log(JSON.stringify(response.data));
m = response.data.votes % 10;
j = response.data.votes % 100;
if(m==0 || m>=5 || (j>=10 && j<=20)) txt_votes = bg_counter.votes5;
else if(m>=2 && m<=4) txt_votes = bg_counter.votes2;
else txt_votes = bg_counter.vote1;
start_rate_index = parseFloat(response.data.score).toFixed(1);
jQuery('#bg_counter_votes').html(response.data.votes);
jQuery('#bg_counter_votes_txt').html(txt_votes);
jQuery('#bg_counter_score').html(start_rate_index);
iniRatingState(start_rate_index, true);
} else {
if (bg_counter.debug) console.log('POST REQUEST: '+request+' ERROR: '+response.error);
}
}
}
}
xhr.send('{"rating": '+number+'}');
}
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