Авто анонс

74
Задумался о добавлении возможности создания анонса. Полез в код… Оказывается, в ливстрит есть все, что нужно для создания анонса! Максу респект!

Но просто добавить новое поле в форму добавления топика мне показалось мало. Точнее я передумал. =)))

Вместо ручного добавления анонса решил сделать авто обрезание текста топика. Варианта три:

1) Отрезать определенное количество символов и тупо ставить троеточие.
2) То же самое, но до первого пробела. В этом случае целостность слов сохраняется.
3) То же самое, но до первого знака окончания строки. :)

Первый тупой и простой никому давно не интересен, поэтому расскажу, как сделать второй и третий.
Заходим в файл \classes\actions\ActionTopic.class.php

Находим строки 386 и 536 с текстом:

$sTextShort=$sText;

Вариант 2. Меняем их на:

// Ищем первый пробел в строке, начиная с 200 по направлению к началу
$sTextShort = substr ($sText, 0, 200 - strlen (strrchr (substr ($sText, 0, 200), ' ')));


Вариант 3. Меняем строки 386 и 536 на:

// Обрезаем все, что больше 200 символов, но только после точки (или других знаков окончания предложения)
preg_match("/.{200}[^.!;?]*[.!;?]/si", $sText.". ", $matches);
$sTextShort = $matches[0];


* * * * UPDATE * * * *

Чтобы была возможность использовать настройку этого хака — либо «да», либо стандартный cut, делаем нижеследующее.

Добавляем в config.php строчку:

define('BLOG_TOPIC_CUT',200); // 0 - используем стандартный cut, больше 0 - обрезаем анонс после этого символа.

Соответственно исправляем в \classes\actions\ActionTopic.class.php:

if (BLOG_TOPIC_CUT > 0 and strlen($sText) > BLOG_TOPIC_CUT) {
	// Обрезаем все, что больше BLOG_TOPIC_CUT символов, но только после точки (или других знаков окончания предложения)
	preg_match("/.{".BLOG_TOPIC_CUT."}[^.!;?]*[.!;?]/si", $sText.". ", $matches);
	$sTextShort = $matches[0];
} else {
	$sTextShort = $sText;
}


* * * * UPDATE 2 * * * *

Если не хотим «портить» конфиг и нас устраивает условие «есть кат — ничего не трогаем, нет ката — обрезаем» — тогда этот вариант для вас. Редактируем только "\classes\actions\ActionTopic.class.php", заменив "$sTextShort=$sText;" из строк 386 и 536 на:

if (strstr ($sText, '<cut>') or strlen ($sText) <= 200) {
	$sTextShort = $sText;
} else {
	// Обрезаем все, что больше 200 символов, но только после точки (или других знаков окончания предложения)
	preg_match("/.200[^.!;?]*[.!;?]/si", $sText.". ", $matches);
	$sTextShort = $matches[0];
}

Комментарии (70)

RSS свернуть / развернуть
это автокат что ли?
0
Ну можно и так сказать. Смысл в том, чтобы анонсы были примерно одного размера. :)
+2
отлично! спасибо. в избранное.
0
Чет не добавляются новости с этим хаком. Пишет:
Notice: Undefined variable: sTextNew in /var/www/tpLVTg/tp.ks.ua/classes/actions/ActionTopic.class.php on line 404
SQL Error: Column 'topic_text' cannot be null at /var/www/tpLVTg/tp.ks.ua/classes/modules/topic/mapper/Topic.mapper.class.php line 64
Array ( [code] => 1048 [message] => Column 'topic_text' cannot be null [query] => INSERT INTO prefix_topic_content (topic_id, topic_text, topic_text_short, topic_text_source, topic_extra ) VALUES
0
Что такое sTextNew?
0
Судя по ошибке, у вас в поле topic_text пишется пустое значение. А такого быть не должно! И мы трогаем не его, а topic_text_short. Переменная sTextShort.
0
наткнулся на еще один подводный кол, при редактировании админом топика, который уже был создан (при первом создании автоматом создается кат), кат убирается, и топик висит во весь рост без ката. Это решаемо?
0
отлично вообще
0
Отлично, давно ломал голову как єто сделать, спасибо!
0
Респект автору!!!
+1
Ага, спасибо! :)
0
Хорошо бы еще оставить альтернативную возможность самому кат сделать ;-)
+1
поддерживаю, необходимо
0
Добавил. UPDATE. :)
+2
сложным путем пошли :)

я скорее предполагал вариант когда кат работает автоматически постоянно, но если вставляешь его вручную, то используется ручной :)
+2
Можно и так, но в конфиг все равно выносить кол-во символов. :)
0
Так было бы более оптимально.
0
Основная идея — примерно одинаковые по длине анонсы. Кат же могут поставить как угодно и где угодно.
0
Кстати, да. Все так и есть — если нету ката, обрезается константой, если есть кат — работает он. Я именно так и хотел. Спасибо :)
0
Тогда вставляем проверку типа:
if (strstr ($sText, '<cut>')) {
0
Чего-то нехватает: если создать и сохранить материал, то обрезается все отлично. Но стоит отредактировать топик, как эффект автоанонса улетучивается. Или это только у меня так?
0
Упс. ))
Ща исправим…
0
Нужно аналогично отредактировать функцию SubmitEdit этого же класса.
0
Да.
0
В том же файле в функции SubmitEdit нужно также заменить $sTextShort=$sText; на то, что описано выше. )
0
Спасибо все равно :)
0
Не за что. :)
0
Спасибо за хак. Возможно в определенных проектах будет полезен.

P.S. Считаю, что пользователь сам должен определять когда необходимо ставить «cut».
0
Зависит от проекта, конечно. И от дизайна. Если хочется все ровно и красиво, неблогоподобно, тогда кату нет. :)
0
Нашел косячок в 3-м варианте. Если длина текста меньше длины анонса, вылетает ошибка и в базу пишется пустое значение. Расширяем проверку:

if (BLOG_TOPIC_CUT > 0 and strlen($sText) > BLOG_TOPIC_CUT) {
+1
strlen на мультибайтовых строках показывает значение длины в 2 раза меньше реального
0
От жеж редиска! Ё!
Просто у мну нет мультибайтовых строк, т.к. хостер не дает, и я от них вообще избавился и всё работает. :)
0
function WinToUtf8($s) {
  $t = '';
  for ($i = 0, $m = strlen($s); $i < $m; $i++) {
    $c = ord($s[$i]);
    if ($c <= 127) { $t .= chr($c); continue; }
    if ($c >= 192 && $c <= 207) { $t .= chr(208) . chr($c - 48); continue; }
    if ($c >= 208 && $c <= 239) { $t .= chr(208) . chr($c - 48); continue; }
    if ($c >= 240 && $c <= 255) { $t .= chr(209) . chr($c - 112); continue; }
    if ($c == 184) { $t .= chr(209) . chr(209); continue; };
    if ($c == 168) { $t .= chr(208) . chr(129); continue; };
  }
  return $t;
}

function Utf8ToWin($fcontents) {
    $out = $c1 = '';
    $byte2 = false;
    for ($c = 0;$c < strlen($fcontents);$c++) {
        $i = ord($fcontents[$c]);
        if ($i <= 127) {
            $out .= $fcontents[$c];
        }
        if ($byte2) {
            $new_c2 = ($c1 & 3) * 64 + ($i & 63);
            $new_c1 = ($c1 >> 2) & 5;
            $new_i = $new_c1 * 256 + $new_c2;
            if ($new_i == 1025) {
                $out_i = 168;
            } else {
                if ($new_i == 1105) {
                    $out_i = 184;
                } else {
                    $out_i = $new_i - 848;
                }
            }
            $out .= chr($out_i);
            $byte2 = false;
        }
        if (($i >> 5) == 6) {
            $c1 = $i;
            $byte2 = true;
        }
    }
    return $out;
}


И прощай mb_string! :)
0
Но кроме того, что нет mb_string, нет и iconv, которой обходится отсутствие mb в ЛС. Вот и изголяюсь. (((
0
кодировка у тебя UTF? значит и текст мультибайтовый
0
utf. наверное, есть. я всё дальше отхожу от кодинга (что радует), многое забывается…
0
вроде как кроме цифр и латиницы
0
ну исходим из того, что сайт на русском языке и в тексте топика количество латиницы пренебрежимо мало :)
0
Есть «костыль», как посчитать кол-во символов в мультибайтовой строке?
0
// choice 1
function utf8_strlen($str) {
  $count = 0;
  for ($i = 0; $i < strlen($str); ++$i) {
    if ((ord($str[$i]) & 0xC0) != 0x80) {
      ++$count;
    }
  }
  return $count;
}

// choice 2
function utf8_strlen($str) {
  return preg_match_all('/[\x00-\x7F\xC0-\xFD]/', $str, $dummy);
}


Вроде работает…
0
А точно mb_string не работает? Если написать mb_strlen($str), то ругается?
0
У меня — да. Если у вас mb стоит — возрадуйтесь! :)
0
Удивительно, 21 век на дворе…
0
Не в Норвегии. =)
0
Хостинг проще сменить чем страну :-)
0
странно, способ «UPDATE 2» — вызвал ошибку при добавлении поста.
а способ из «update» — сразу заработал, им и пользуюсь :)
Автору огромное спасибо!
+1
Для устранения ошибки в UPDATE 2 следует писать такой код:
if (strstr ($sText, '<cut>') or strlen ($sText) <= 200) {
        $sTextShort = $sText;
} else {
        // Обрезаем все, что больше 200 символов, но только после точки (или других знаков окончания предложения)
        preg_match("/.{200}[^.!;?]*[.!;?]/si", $sText.". ", $matches);
        $sTextShort = $matches[0];
}

Автор забыл в строке…
preg_match("/.200[^.!;?]*[.!;?]/si", $sText.". ", $matches);

… число (в данном случае 200) заключить в фигурные скобки.

Я у себя на проекте заключил — все работает.
Автору плюс. Т.к. очень нужная для мну штука. Благодарствую.
0
А можно ли сделать кат не по колличеству символов, а по высоте блока. Например, чтобы отрезало когда пост больше 150px?
0
  • avatar
  • Judge
  • 23 августа 2009, 11:40
Как вы себе это представляете? :)
Тогда для «резиновых» сайтов придётся и ширину, и высоту учитывать. :)
+1
Я как раз и не представлял как это сделать, потому и спросил.
СПС за ответ
0
это можно через цсс сделать, сделать отдельный класс для блока в темплейте вывода всех постов для отдельного поста и в нём что то такое max-height:150px; overflow-y:hidden; и если текста будет больше чем на 150 пикселей в высоту они будут просто не видны. если ограничиться еще кол-вом символов, то те несколько строк лишнего текста не будут мешать
0
Вдруг обратил внимание на странную вещь. Я ставлю у себя кол-во символов 3000 до автовставки тега cut. Но почему то вставляется в р-не 1700-го символа. Если ставлю 2000 символов ограничение — обрезается в р-не 1200 символа. В чем подвох? оО
0
  • avatar
  • g3n0m
  • 28 сентября 2009, 16:26
Пробелы считаешь?
+1
Эээ… признаться честно — не знаю. Судя по кол-ву выводимых перед катом символов — не считает. Тогда встречный вопрос — как посчитать и их тоже?
0
Ну я имею ввиду как вы определяете что выводит 1200 вместо 2000? Измеряете на выходе функцией strlen? Или как?
0
в редакторе (notepad++) смотрю сколько выводит символов перед катом ))
0
на сколько я понимаю такая разница происходит из-за того что функция preg_match встроенная в php по разному отрабатывает символы кириллицы и латиницы.
Потому как в том же notepad++
Для латинского текста вывел 1019 chars 1029 bytes
Для кирилицы — 556 chars 1018 bytes
Скорее всего константа BLOG_TOPIC_CUT для preg_match в строке
preg_match("/.{".BLOG_TOPIC_CUT."}[^.!;?]*[.!;?]/si", $sText.". ", $matches);
Указывает кол-во байт а не символов.
Подскажите гуру php как побороть данный вопрос?
+1
Как вариант:
mb_ereg_match("/.{".BLOG_TOPIC_CUT."}[^.!;?]*[.!;?]/si", $sText.". ", $matches);
$sTextShort = $matches[0];

заменить на
$tmp_str = iconv("UTF-8", "CP1251", $sText);
preg_match("/.{".BLOG_TOPIC_CUT."}[^.!;?]*[.!;?]/si", $tmp_str.". ", $matches);
$sTextShort = iconv("CP1251", "UTF-8", $matches[0]);

Проверил для русского текста результат 1004 char 1816 bytes при настройке BLOG_TOPIC_CUT — 1000.

Для предыдущего комментария BLOG_TOPIC_CUT тоже 1000.
+1
Корректируем
$tmp_str = iconv(«UTF-8», "CP1251", $sText);
в
$tmp_str = iconv(«UTF-8», "CP1251//IGNORE", $sText);
чтобы не было
iconv() [function.iconv]: Detected an illegal character in input string
+1
К сожалению публикации меньше заданного чиста символов BLOG_TOPIC_CUT выдают ошибку :(
0
Вот кстати с модулем какой глюк вылез livestreet.ru/blog/questions/3068.html
0
а для версии 0.4 как подправить?
0
Ребята, а как сделать авто анонс для версии 0.4.2? Может кто-то делал, помогите советом или примером. Это актуально для владельцев версии 0.4.2.
0
точно-точно) поддерживаю 2 топика выше)
0
+1 к вышесказанному
0
напишите пожалуйста как работает на текущей версии: LiveStreet 0.4.2?
0
Здесь уже встроенная функция cut есть.
Просто заключите нужный текст в тег при создании топика :)
0
Вот тег:
<cut> 
:)
-1
0
Пользователи могут пользоваться тего кат не так, как хочется автору проекта, лучше обрезать столько символов, сколько нужно. Млм.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.