Выводим в Top блогов количество постов вместо рейтинга.

Возникла задача выводить в блоке Tоп блогов вместо абстрактного рейтинга количество постов. Актуально для новых сайтов или неактивных комьюнити.



Для начала находим Экшен блока. Структура LS подробно описана, поэтому легко находим нужный блок: /classes/blocks/BlockBlogs.class.php В блоке вызывается единственная функция: Blog_GetBlogsRating, с ней и будем работать.

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


Шаг 1. Инициализируем модуль

Есть достаточно много статей описывающих как написать простой модуль, поэтому останавливаться на этом вопросе не будем. Создаем папку /plugins/topblogs2 и в ней делаем XML описание плагина, файл plugin.xml:

<?xml version="1.0" encoding="UTF-8"?>
<plugin>
    <name>
        <lang name="default">TopBlogs2</lang>
    </name>
    <author>
        <lang name="default">Begetan</lang>
    </author>
    <homepage></homepage>
    <version>0.1</version>
    <requires>
        <livestreet>0.5.0</livestreet>
        <plugins>
        </plugins>
    </requires>
    <description>
        <lang name="default">Show top rated blogs by count of posts instead of standart LiveStreet blog's rating</lang>
        <lang name="russian">Выводит топ блогов по количеству постов, а не по стандартному рейтингу блогов LiveStreet</lang>
    </description>
</plugin>

Далее создаем класс активации нашего плагина — /plugins/topblogs2/PluginTopblogs2.class.php:

if (!class_exists('Plugin')) die('Are you sure?');

class PluginTopBlogs2 extends Plugin
{
    protected $aInherits=array(
        'module' => array('ModuleBlog' => '_ModuleTop'),
    );

    public function Activate() {
        return true;
    }

    public function Init() {
    }
}

Подробное описание механизма наследования и переопределения функции читайте тут. В нашем случае переопределяются функции Модуля Blog наследником нашего локального Модуля Top. Обратите внимание на подчеркивание, которое сокращает полную запись PluginTopBlogs2_ModuleTop.

Шаг 2. Пишем код модуля

Согласно тем названиям, которые мы придумали и объявили в конфигурации плагина код модуля должен находится в файле: /plugins/topblogs2/classes/modules/top/Top.class.php:


<?php
class PluginTopBlogs2_ModuleTop extends PluginTopBlogs2_Inherit_ModuleBlog {

        protected $oMapperBlog2;

        public function GetBlogsRating($iCurrPage,$iPerPage) {

                $this->oMapperBlog2 = Engine::GetMapper ( __CLASS__ );

#               $aResult=parent::GetBlogsRating($iCurrPage, $iPerPage);
                $aResult=$this->GetTopBlogsByPosts($iCurrPage, $iPerPage);
                return $aResult;
        }

        public function GetTopBlogsByPosts($iCurrPage,$iPerPage) {
                list ($aTopBlogs, $aRating) = $this->oMapperBlog2->GetTopBlogsByPosts($iCount,$iCurrPage,$iPerPage);
                $data = array('collection'=>$aTopBlogs,'count'=>$iCount);
                $aBlogs = parent::GetBlogsAdditionalData($data['collection'],array('owner'=>array(),'relation_user'));
                # Подменяем рейтинг блога на новый
                foreach ( $aBlogs as $oBlog ) {
                        $oBlog->setRating($aRating[$oBlog->getId()]);
                        $data2[] = $oBlog;
                }
                # Обновляем список блогов
                $data['collection'] = $data2;
                return $data;
        }
}
?>

Сначала объявляем стандартную функцию GetBlogsRating для того, чтобы переопределить ее в нашем файле. Затем из нее мы вызываем уже нашу функцию GetTopBlogsByPosts, которая и будет делать то что нам нужно. При отладке может возникнуть желание вызвать исходную функцию GetBlogsRating, пример такого вызова в строчке с комментарием.

Обратите внимание, что мы инициализировали свой Маппер, поскольку нам потребуется еще работа с базой данных.
Не применяется кеширование, поскольку мы получаем из Маппера два массива. Придумывать корректный алгоритм было лень, тем более что в моих проектах пока проблемы с нагрузкой не стоит.

Затем мы для всех блогов подменяем поле рейтинг значением из второго массива, содержащего количество постов в каждом блоге. Этот нехитрый трюк позволяет сделать модуль совместимым с абсолютно любым шаблоном, поскольку вся информация в отображение поступает только в стандартных массивах и объектах.

Шаг 3. Пишем код маппера

Маппер у нас окажется тут: /plugins/topblogs2/classes/modules/top/mapper/Top.mapper.class.php.


<?php

class PluginTopBlogs2_ModuleTop_MapperTop  extends Mapper {

        public function GetTopBlogsByPosts (&$iCount,$iCurrPage,$iPerPage) {
                $sql = "SELECT t.blog_id, COUNT(t.blog_id) as rating " .
                        "FROM ".Config::Get('db.table.topic')." as t " .
                        "GROUP BY t.blog_id " .
                        "ORDER BY 2 DESC " .
                        "LIMIT ?d, ?d";

                $aReturn=array();
                $aReturn2=array();
                if ($aRows=$this->oDb->selectPage($iCount,$sql,($iCurrPage-1)*$iPerPage, $iPerPage)) {
                        foreach ($aRows as $aRow) {
                                $aReturn[]=$aRow['blog_id'];
                                $aReturn2[$aRow['blog_id']]=$aRow['rating'];
                        }
                }
                return array ($aReturn, $aReturn2);
        }
}
?>

В отличие от стандартной функции мы возвращаем два массива — массив ID найденных блогов и ассоциативный массив блог->рейтинг. Сделано так потому что в стандартном объекте «блог» нет значения количества постов. Наверно можно было расширить свойства блога, но так было проще. Буду рад услышать предложения и идеи как изменить или улучшить код.

Аналогично нужно изменить функции GetBlogsRatingJoin и GetBlogsRatingSelf чтобы получился законченный модуль.

Теперь одним движением руки активируя или деактивируя модуль, получаем результат приведенный на скриншотах в начале текста. Если уважаемая публика проявит заинтересованность, то оформлю в виде модуля и выложу в каталог. На сегодня все.

27 комментариев

avatar
Довольно таки не плохо.
avatar
Довольно таки неплохо? Да вы шутите! Это же просто отличный мануал по плагинам, которых так не хватает!
avatar
Rage guy! За что опять минус? Вы хоть обоснуйте?
avatar
Это вообще очень очень!
Это именно то чего не хватало, но теперь оно есть :))
avatar
Да ну вас. Заминусовали до полусмерти.
avatar
Зачем выводить число топиков нецелым числом?
avatar
В отображение передается целое число, а дальше где то в шаблоне формируется вид. Надо править шаблон.
avatar
Думаю надо в кэш складывать количество топиков для блогов, ну и обновлять это значение при написании новых топиков. Ведь отправлять базе запрос на просчёт количества топиков при каждой загрузке страницы — не самое верное решение…
avatar
Точно, кажется про это здесь было livestreet.ru/blog/dev_documentation/9019.html
avatar
бновлять это значение при написании новых топиков

Вот с этим и сложности. Можно ли вызывать метод модуля при возникновении в системе события «создание нового топика»? Через хуки?
avatar
Да, конечно можно. Если мне память не изменяет то хуки «topic_edit_before» и «topic_edit_after» — где-то сюда вешать обновление кэша надо
avatar
Вот тут описан способ изменения рейтинга для блогов. Как вариант. Для 0.4.2.
livestreet.ru/blog/6429.html
avatar
ТС, было бы здорово, если б вы оформили в виде плагина и выложили в каталог.
avatar
да, полностью поддерживаю, плагин пользовался бы популярностью
avatar
Я тоже буду ждать плагин. Очень здравая мысль, кстати: отменить соревнование блогов.
avatar
Соревнование — только польза для сайта. конкуренция всегд адолжна быть, и благодаря ей, сайт будет быстрее наполняться контентом. ИМХО
avatar
Между юзерами — да. А какой смысл в соревновании блога для разработчиков на этом, например, сайте — с блогом «Биржа заказов на разработку и поддержку за деньги»? Как соревнование между ними двумя поможет сайту быстрее наполняться контентом? Никак.
avatar
Просьба все таки опубликовать подробную инструкцию или же выпустить в виде плагина!
avatar
Fatal error: Class 'PluginTopBlogs2_ModuleTop' not found in /var/www/virtual/leiunurk.ee/htdocs/engine/classes/Engine.class.php on line 316

A nu da, potom tolko uvidel
Аналогично нужно изменить функции GetBlogsRatingJoin и GetBlogsRatingSelf чтобы получился законченный модуль.
chto modul to ne do konza opisan. Pllease vylozhyte polnoe opisanie. Avtoru spasibo.
avatar
долго ломал голову над этой ошибкой, пока пытался запустить этот плагин на локальной машине. потом плюнул и решил закинуть на сервер и тестануть и, о чудо, плагин заработал…
может кто сталкивался? под denwer работал
avatar
Плагин Вы доделали до конца?
avatar
делаю потихоньку. в ЛС новичок, поэтому много нового познать надо =) если сделается раньше, чем тут выложит кто-нибудь, то сам скину ссылку…
avatar
Тут всем пофигу на этот плагин, буду Ждать завершения!
avatar
Нет никаких новостей?
avatar
хотелось бы увидеть описание построения до конца.
avatar
Интересный плагин, пожалуйста добавьте полное описание!
avatar
А есть подобное решение для 2.0? Рейтинг на данный момент не так актуален, как количество постов в блогах.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.