+4.52
5 читателей, 84 топика

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

Для начала находим Экшен блока. Структура 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() {
    }
}

Шаг 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 чтобы получился законченный модуль.

Удаление UTF-8 BOM из консоли

linux (debian)
find путь/к/лайвстриту/ -type f \( -name '*.tpl' -o -name '*.php' \) -exec sed -i '1 s/^\xef\xbb\xbf//' {} \;

freebsd (7.2)
find ./ -type f \( -name '*.tpl' -o -name '*.php' \) -exec sed -i -e '1 s/^\xef\xbb\xbf//' {} \;

sed почему-то иногда не отрабатывает, поэтому php, find, awk, xargs:
php -r "ob_start();
passthru('find ./ -type f \( -name \'*.tpl\' -o -name \'*.php\' \) -print0 | xargs -0r awk \'/^\xEF\xBB\xBF/ {print FILENAME}{nextfile}\'');
foreach(array_filter(explode(\"\n\",ob_get_clean())) as \$f){
        echo \"remove BOM from \$f...\n\";
        file_put_contents(\$f, substr(file_get_contents(\$f), 3));
};"

Хранение img на бесплатном сервисе ImageShack




Фотографии сперва ресайзатся, потом заливаются на сервер ImageShack.
Поддерживаются: вставка изображения в топики, комментарии к ним, аватарки, фотка в профайле, и фотосет.

Реализована поддержка одного флага в конфиге, называется: do_local_reserve_copy. Если установить данный флаг в true, то фотография после ресайза не будет удалятся с вашего сервера, так же в БД будет добавлено строчка соответствия вида: файл на сервере ImageShack — файл на вашем сервере. Для чего это нужно. Для того, что бы если вдруг по каким-то причинам вас забанят, вы сможете восстановится с данного бекапа. если do_local_reserve_copy false, то файл после заливки на сервер ImageShack удаляется с вашего сервера.

Получить ключ dev key для вашего домена здесь: stream.imageshack.us/api/

Скачать плагин: 2me.be/x/imageshack.rar
зеркало с гугл сервисов.

Выделяем цветом комментарии топикстартера

Итак. Сделать это оказалось довольно легко. Как и с комментариями админа все делается также в два действия.

1. В файле comment.tpl находим следующие строчки:
<div id="comment_id_{$oComment->getId()}" class="comment {if !$oUserCurrent or ($oUserCurrent and !$oUserCurrent->isAdministrator())}not-admin{/if} {if $oComment->getDelete()} deleted{elseif $oUserCurrent and $oComment->getUserId()==$oUserCurrent->getId()} self{elseif $sDateReadLast<=$oComment->getDate()} new{/if}" >

и добавляем:
{if $oTopic and $oComment->getUserId() == $oTopic->getUserId()}topicstart{/if}

получаем:
<div id="comment_id_{$oComment->getId()}" class="comment {if !$oUserCurrent or ($oUserCurrent and !$oUserCurrent->isAdministrator())}not-admin{/if} {if $oComment->getDelete()} deleted{elseif $oUserCurrent and $oComment->getUserId()==$oUserCurrent->getId()} self{elseif $sDateReadLast<=$oComment->getDate()} new{/if} {if $oTopic and $oComment->getUserId() == $oTopic->getUserId()}topicstart{/if}" >

2. В файле comments.css добавляем стиль:
.comment.topicstart  { background: #желаемый цвет; }

Вот собственно и все. Напомню, что при должной сноровке и смекалке можно изменить не только цвет блока.

Другой цвет у комментариев админа

После несложных манипуляций можно получить другое визуальное оформление комментариев оставленных администратором сайта.
Все делается всего в два действия:
1. В файле comment.tpl в следующие строчки:
<div id="comment_id_{$oComment->getId()}" class="comment {if !$oUserCurrent or ($oUserCurrent and !$oUserCurrent->isAdministrator())}not-admin{/if} {if $oComment->getDelete()} deleted{elseif $oUserCurrent and $oComment->getUserId()==$oUserCurrent->getId()} self{elseif $sDateReadLast<=$oComment->getDate()} new{/if}" >

добавляем:
{if $oUser->isAdministrator()}admin{else}user{/if}

получаем:
<div id="comment_id_{$oComment->getId()}" class="comment {if !$oUserCurrent or ($oUserCurrent and !$oUserCurrent->isAdministrator())}not-admin{/if} {if $oComment->getDelete()} deleted{elseif $oUserCurrent and $oComment->getUserId()==$oUserCurrent->getId()} self{elseif $sDateReadLast<=$oComment->getDate()} new{/if} {if $oUser->isAdministrator()}admin{else}user{/if}"  >

2. В файле comments.css добавляем стиль:
.comment.admin  { background: #желаемый цвет; }

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

Плагин Amason S3

После активации, обеспечит хранение загруженных картинок на серверах amason s3.

Фотографии сперва ресайзатся, потом заливаются на сервер амазон.
Поддерживаются: всавка изображения в топики, комментарии к ним, аватарки, фотка в профайле, и фотосет.

Скачать: 2me.be/z/amasons3_0.1.1.zip

Установка reCAPTCHA на LiveStreet

Итак, идем сюда и получаем ключи: Public Key и Private Key. Public будем вставлять в JavaScript и он может быть найден в исходном коде, Private нужно хранить в секрете и использовать только на стороне сервера.
Итак, приступаем к замене каптчи. Идем в /templates/skin/название-темы/actions/ActionRegistration и открываем файл index.tpl, в котором заменяем
<img src="{cfg name='path.root.engine_lib'}/external/kcaptcha/index.php?{$_sPhpSessionName}={$_sPhpSessionId}" onclick="this.src='{cfg name='path.root.engine_lib'}/external/kcaptcha/index.php?{$_sPhpSessionName}={$_sPhpSessionId}&n='+Math.random();" />
 
		<p><input type="text" name="captcha" value="" maxlength="3" class="input-100" /></p>

на
<script type="text/javascript" src="http://api.recaptcha.net/challenge?k=ЗДЕСЬ_ВАШ_Public_Key">
</script><noscript>Включите JavaScript или обновите ваш браузер!</noscript>

Только не забудьте заменить ЗДЕСЬ_ВАШ_Public_Key на полученный ранее Public Key. Перед этим еще можно добавить
<script type="text/javascript">
        var RecaptchaOptions = {
                custom_translations : {
                        instructions_visual : "Введите два слова:",
                        instructions_audio : "Введите что вы слышите",
                        play_again : "Включить заново",
                        cant_hear_this : "Скачать в формате MP3",
                        visual_challenge : "Визуальный режим",
                        audio_challenge : "Режим аудио",
                        refresh_btn : "Обновить",
                        help_btn : "Помощь",
                        incorrect_try_again : "Неверно. Пожалуйста, попробуйте еще раз.",
                },
                lang : 'ru', // Unavailable while writing this code (just for audio challenge)
                theme : 'white' // Make sure there is no trailing ',' at the end of the RecaptchaOptions dictionary
        };
		</script>

для русификации. Подробнее о кастомизации каптчи смотрите здесь.

Далее качаем саму библиотеку каптчи отсюда, распаковываем и кладем её содержимое в /engine/lib/external/recaptcha. Далее идем в /classes/actions, открываем файл ActionRegistration.class.php. Добавляем в начало файла подключение библиотеки
require_once ($_SERVER['DOCUMENT_ROOT']."/engine/lib/external/recaptcha/recaptchalib.php");

Затем удаляем или комментируем
if (!isset($_SESSION['captcha_keystring']) or $_SESSION['captcha_keystring']!=strtolower(getRequest('captcha'))) {
				$this->Message_AddError($this->Lang_Get('registration_captcha_error'),$this->Lang_Get('error'));
				$bError=true;

и добавляем
$resp = null;
if (array_key_exists('recaptcha_response_field',$_POST)){
$resp = recaptcha_check_answer ('ЗДЕСЬ_ВАШ_Private_Key',$_SERVER["REMOTE_ADDR"],$_POST["recaptcha_challenge_field"],$_POST["recaptcha_response_field"]);}
if ($resp==null or !$resp->is_valid){
$this->Message_AddError($this->Lang_Get('registration_captcha_error'),$this->Lang_Get('error'));
$bError=true;
}

набор плагинов, для 0.4.x

Есть как платные, так и нет.
  • Allows users to create Counter-Strike mixes
  • Custom Block Manager for LiveStreet/ACE
  • Allows users to display their own Google Adsense ads in their topics
  • Alternative navigation
  • Attachments
  • Blog Autoconnect plugin
  • Belcam
  • Birthday Block
  • Chat plugin
  • Change Date
  • Comments on static pages
  • Livestreet Company Plugin
  • LiveStreet Engine Social Networking
  • Delayed post
  • Statistic plugin
  • Gravatar
  • Groups
  • Livestreet Ideal Interface
  • Image Preview
  • Livestreet Job Plugin
  • Mini Flv player
  • FindPresent
  • Seolib
  • LS Ads
  • LsBlocks
  • Index page title changer
  • My Stuff
  • NiceURL
  • Note
  • Only personal topics in user`s profile
  • Livestreet Image Gallery
  • Game Servers
  • Events: Events, Directory Places
  • Comments Edit
  • Microblog Plugin
  • Purse+Tasks
  • Torrent
  • Mixes module
  • QIP Smiles
  • Questions
  • RusUrls
  • Similar topics
  • Sitemap
  • Skin Switch
  • Contacts fields
  • Discussion Stream
  • All tags
  • Teams
  • Textarearesize
  • Preview-image for topic
  • Topic loader
  • Block TV
  • Livestreet Userhacks Plugin
  • Weather
  • XText

Скачать:

Поддомены для юзеров и коллективных блогов под 0.5

  • Все посты располагаются в субдоменах
  • Ссылки из заголовков топиков с главной страницы, rss, прямого эфира, топа, хороших и тд ведут на полный текст, располагающийся в субдомене
  • Ссылки из пользовательских профилей ведут на профили друзей, а не на их блоги, например, user.site.ru/profile;
  • Ссылки из списка блогов и из пользовательских профилей (состоит/администрирует) ведут на субдомены, являющимися коллективными блогами.
  • по адресу user.site.ru показываем публикации (блог пользователя), а не его профиль;
  • по адресу blog.site.ru показываем непосредственно сам коллективный блог;
  • ссылки на субдомены, для которых нет алиасов среди блогов и пользователей, переадресовываются на основной домен и по ним выводится ошибка 404;
  • обеспечение предупреждения коллизий путём проверки существования алиасов при регистрации пользователей и создания коллективных блогов.

Прежде всего нужно настроить DNS и параметры хостинга:
Для настройки DNS вам нужно привязать все поддомены к основному сайту. Для этого направьте wildcard домен вида *.site.ru на IP-адрес основного домена site.ru. Далее, вам нужно поставить обработку всех поддоменов вашего основного домена аккаунтом вашего основного домена. Например, если вы используете apache, то вам нужно прописать синоним для имени хоста директивой ServerAlias *.site.ru.

Если в plugins есть доступ на запись веб-серверу, то плагин сам создаст файл /plugins/subdomains/config.local.php и пропишет там ваш текущий домен в качестве базового. В этом случае больше никаких действий по установке предпринимать не требуется, ваш
плагин установлен. Если же после активации возникли проблемы с отображением сайта, то пропишите базовый домен вашего сайта в файле /plugins/subdomains/config.php таким образом: $config['main_domain'] = 'mysite.ru';
В настройках /plugins/subdomains/config/config.php есть список имён поддоменов $config['forbidden_subdomains'], которые запрещено регистрировать пользователям. Пользователи с такими логинами и блоги с такими URL регистрироваться не будут. Можете убрать или добавить необходимые домены по вашему желанию. Также при активации плагин проверяет наличие пользователей с логинами, совпадающими с URL блогов, и со списком запрещённых субдоменов. В том случае, если плагин таковые находит, он выводит соообщение об ошибке и запрещает активацию. Для продолжения активации вы можете либо переименовать пользователей/блоги, либо убрать соответствующие домены в списке запрещённых доменов.

Скачать