Как настроить отображение числа комментариев в Disqus 2012 по своему вкусу
25 февраля 2013
В старом Disqus, так называемом Disqus Classic, была возможность настраивать то, как будет отображаться количество комментариев к статьям. Например, если комментариев нет, на ваше усмотрение Disqus мог писать «0 комментариев», «Комментарии отсутствуют», «Нет комментариев» и тп. В Disqus 2012 такая возможность пропала. Раньше проблема решалась временным переключением на старый Disqus, но теперь и этой возможности нет.
А я как раз давно подумывал над тем, чтобы перейти с такого отображения числа комментариев:
… на такое:
Тогда я мог бы писать заголовки произвольной длины и они смотрелись бы по-человечески. Также, если число комментариев у какого-нибудь поста вдруг перевалит за сотню, оно будет нормально отображено. Да и страницы бложика будут грузиться чуточку быстрее за счет избавления от ненужных украшательств.
В связи с тем, что в свое время я сказал Disqus’у выводить просто число комментариев безо всяких там слов, а возможности как-то это изменить теперь нет, спрашивается, что делать-то? Погуглив немного я не смог найти какой-либо воркэраунд. Пришлось придумывать свой.
Оказалось, что Disqus отдает информацию о числе комментариев к заданному множеству статей в ответ на запрос типа:
Здесь ID — это идентификатор вашего сайта в Disqus, а URL1, URL2 и тд — адреса статей, для которых требуется получить количество комментариев. В ответ приходит JavaScript, который ищет на текущей странице отрывки кода вроде:
… и заменяет текст внутри тэга на число комментариев.
Я набросал такой скрипт:
// error_reporting(E_ALL);
$secret = "SECRET!";
header("Content-type: text/javascript");
if(!isset($_GET['q']) || !isset($_GET['s']) ||
md5($secret.$_GET['q']) != $_GET['s']) {
echo "// invalid query checksum\n";
exit;
}
if(rand(1,512) == 1) {
// удаляем файлы, созданные более суток назад
echo "// you are lucky, cleaning cache...\n";
system("find ./cache -mtime +1 -delete");
}
$cache = "./cache/".md5($secret.$_GET['s'].floor(time() / (30 * 60)));
if(file_exists($cache)) {
$numbers = file_get_contents($cache);
echo "// cached\n";
} else {
$url = "http://disqus.com/forums/eaxme/get_num_replies.js?".
$_GET['q'];
$data = file_get_contents($url);
preg_match("/var num_replies = '([^']*)'/", $data, $matches);
$numbers = $matches[1];
file_put_contents($cache, $numbers);
}
?>
(function () {
var nodes = document.getElementsByTagName('a');
var disqus_nodes = [];
var _node_is_disqus = function(node) {
return (node.href.indexOf('#disqus_thread') >= 0);
}
var i;
for (i = 0; i < nodes.length; i++) {
try {
if (_node_is_disqus(nodes[i])) {
disqus_nodes.push(nodes[i]);
}
} catch(e) {
}
}
var num_replies = '<?php echo $numbers ?>'.split(',');
var replies_count, link_text;
for (i = 0; i < disqus_nodes.length; i++) {
link_text = '';
template = '';
replies_count = parseInt(num_replies[i], 10);
if (replies_count !== undefined && !isNaN(replies_count)) {
rem = replies_count % 10;
if (replies_count > 10 && replies_count < 15) {
template = '{num} комментариев';
} else if (rem > 1 && rem < 5) {
template = '{num} комментария';
} else if (rem == 1) {
template = '{num} комментарий';
} else {
template = '{num} комментариев';
}
link_text = template.replace('{num}', replies_count);
}
if (link_text) {
try {
disqus_nodes[i].innerHTML = link_text;
} catch(e) {
if (disqus_nodes[i].innerText) {
disqus_nodes[i].innerText = link_text;
}
}
}
}
})();
Скрипт представляет собой своего рода прокси для get_num_replies.js. Он принимает два аргумента — q и s. Первый представляет собой запрос, который должен быть послан get_num_replies.js, а второй — что-то вроде цифровой подписи аргумента q, на всякий случай. Если подпись верна, скрипт шлет запрос на сервер Disqus’а, парсит ответ регулярным выражением, и возвращает немного модифицированный ответ. Чтобы не ходить слишком часто по HTTP, ответы от Disqus’а кэшируются.
Также я добавил в functions.php такой кусок кода:
echo '<script type="text/javascript" src="'.
'http://eax.me/disqus-comments/?q='.
urlencode($commentsNumberQuery).
'&s='.md5("SECRET!".$commentsNumberQuery).
'"></script>';
}
… вывод постов в index.php, archive.php и single.php изменил следующим образом:
global $commentsNumberQuery;
$commentsNumberQuery = "";
$postNumber = 0;
while(have_posts()):
the_post();
$postNumber++;
$commentsNumberQuery .= "url".$postNumber."=".get_permalink()."&";
?>
… а в footer.php дописал:
global $commentsNumberQuery;
comments_number_javascript($commentsNumberQuery);
?>
</body>
</html>
В результате я убил сразу трех зайцев:
- Решил основную задачу — выводить число комментариев в формате «N комментариев»;
- Немного ускорил работу бложика (меньше картинок, меньше редиректов, кэширование ответа от Disqus);
- Настроил вывод числа комментариев в полном соответствии с правилами русского языка;
Есть подозрение, что последнего вообще никогда не будет в Disqus. И решение даже получилось почти не костыльным. В общем, я доволен. А вы что скажите?
P.S. Кстати, можете меня поздравить. Это мой двухсотый пост в этом блоге.
Дополнение: К сожалению, описанный здесь API жестко привязывается к URL статьи. Если вы решите изменить этот URL, число комментариев станет перманентно равно нулю. Для решения этой проблемы можно дергать http://disqus.com/embed/comments/?f=FORUM&t_i=POSTID
, где FORUM — это идентификатор вашего сайта, например eaxme
, а POSTID — идентификатор поста в urlencode, например 18014%20http%3A%2F%2Feax.me%2F%3Fp%3D18014
, и выдирать оттуда число комментариев. Только работать это будет несколько медленнее.
Метки: PHP, WordPress, Сайтостроение.
Вы можете прислать свой комментарий мне на почту, или воспользоваться комментариями в Telegram-группе.