[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Хранение текста и разметки отдельно
kirik
Вот сегодня вечерком меня переклинило, и захотелось что-нибудь бесполезное написать smile.gif
Получился класс для разделения мух от котлет текста от разметки.
Зачем? А я сам не знаю.. Мне кажется прикольно хранить разметку в одном месте, а текст в другом cool.gif Так мы получаем чистый текст, с которым можно без проблем работать при поиске а так же возможность воротить все взад, при выводе. И при этом у нас не будет избыточности в БД (ну или в файлах).
Это конечно же все теория, не знаю как оно будет работать на практике, но вот на ваш суд smile.gif

сам класс
/**
* Класс для отделения разметки от текста
* Написал: kirik [
kirik-san@users.sourceforge.net]
* Версия: 0.1a
**/

class cleanUpText
{
/**
*
@var $plain_text здесь будет лежать чистый текст без разметки
**/

private $plain_text = '';

/**
*
@var $markup массив для хранения разметки (массив вида 'позиция в строке' => 'разметка')
**/

private $markup = array();

/**
*
@var $special массив для хранения специальных символов
**/

private $special = array();

/**
* - Разделяем текст и разметку
*
@fn cleanText( string $text, array $tags = array('<', '>'), array $special = array("\n", "\r", "\t") )
*
@param $text сюда передаем "грязный текст" с разметкой
*
@param $tags этим массивом можно определить что считать за тэги: нулевой элемент - открывающийся тэг, первый - закрывающийся
*
@param $special здесь можно определить какие символы так же считать разметкой
**/

public function cleanText($text, $tags = array('<', '>'), $special = array("\n", "\r", "\t"))
{
$this->markup_text = $text;
$this->special = $special;
for($i = 0, $c = mb_strlen($text), $pos = 0, $open = false; $i < $c; $i++)
{
$char = mb_substr($text, $i, 1);
$spec = false;

if(($char == $tags[0]
&& ((
$n = $i + 1) < $c)
&& ((
$ord = ord(strtolower(mb_substr($text, $n, 1)))) > 96 && $ord < 123 || $ord == 47))
|| (!
$open && ($spec = in_array($char, $special)))
)

{
if(empty($this->markup[$pos]))
{
$this->markup[$pos] = '';
}

$this->markup[$pos] .= $char;
if($spec)
{
$this->plain_text .= ' ';
$pos++;
}
else
{
$open = true;
}
}

elseif($char == $tags[1] && $open)
{
$this->markup[$pos] .= $char;
$open = false;
}
elseif($open)
{
$this->markup[$pos] .= $char;
}
else
{
$pos++;
$this->plain_text .= $char;
}
}
}


/**
* - Соединяем чистый текст и разметку
*
@fn markUpText( string $plain_text, array $markup)
*
@param $plain_text сюда передаем "чистый текст" без разметки
*
@param $markup сюда передаем разметку
**/

public function markUpText($plain_text, $markup)
{
$markup_text = '';
$this->markup = $markup;
$this->plain_text = $plain_text;

for($i = 0, $c = mb_strlen($plain_text); $i < $c; $i++)
{
if(isset($markup[$i]))
{
$markup_text .= $markup[$i];
if(in_array($markup[$i], $this->special))
{
continue;
}
}


$markup_text .= mb_substr($plain_text, $i, 1);
}

if(isset($markup[$i]))
{
$markup_text .= $markup[$i];
}

return $markup_text;
}

/**
* - Забираем чистый текст
*
@fn getPlain( void )
**/

public function getPlain()
{
return $this->plain_text;
}

/**
* - Забираем разметку
*
@fn getMarkup( void )
**/

public function getMarkup()
{
return $this->markup;
}
}


пример с bb кодами
$text = '[SIZE=8 ]Тестовое задание[/SIZE ]

[SIZE=6 ]Задание на JavaScript[/SIZE ]

Создать комплекс из 2-х страниц. На первой странице есть форма:
Текстовое поле [ + ]
[ Отправить ]'
;

$cut = new cleanUpText;
$cut->cleanText($text, array('[', ']')); // разделяем текст и разметку
$plain_text = $cut->getPlain(); // забираем чистый текст (в одну строку)
$markup = $cut->getMarkup(); // забираем разметку
$markup_sz = serialize($markup); // сериализуем массив с разметкой
/// Все! Переменные $plain_text и $markup_sz можно уже заносить в БД, в соседние поля


$markup_usz = unserialize($markup_sz); // Переводим сериализованную разметку в массив
$result_text = $cut->markUpText($plain_text, $markup_usz); // Воссоединяем текст и разметку

echo 'Original text: ' . $text . "\n\n";
echo 'Clean text: ' . $plain_text . "\n\n";
echo 'Serialized markup: ' . $markup_sz . "\n\n";
echo 'Mark upped text: ' . $result_text . "\n\n";


пример с html
$text = '<tr>
<td colspan="2" class="pformstrip">Установки темы</td>
</tr>
<tr>
<td class="pformleft">Название темы</td>
<td class="pformright"><input size="40" maxlength="50" name="TopicTitle" value="" tabindex="1" class="forminput" type="text"></td>

</tr>
<tr>
<td class="pformleft">Описание темы</td>
<td class="pformright"><input size="40" maxlength="40" name="TopicDesc" value="" tabindex="2" class="forminput" type="text"></td>
</tr>'
;

$cut = new cleanUpText;
$cut->cleanText($text); // разделяем текст и разметку
$plain_text = $cut->getPlain(); // забираем чистый текст (в одну строку)
$markup = $cut->getMarkup(); // забираем разметку
$markup_sz = serialize($markup); // сериализуем массив с разметкой
/// Все! Переменные $plain_text и $markup_sz можно уже заносить в БД, в соседние поля


$markup_usz = unserialize($markup_sz); // Переводим сериализованную разметку в массив
$result_text = $cut->markUpText($plain_text, $markup_usz); // Воссоединяем текст и разметку

echo 'Original text: ' . $text . "\n\n";
echo 'Clean text: ' . $plain_text . "\n\n";
echo 'Serialized markup: ' . $markup_sz . "\n\n";
echo 'Mark upped text: ' . $result_text . "\n\n";


А если хочется иметь на выходе текст без знаков препинания, скобочек и прочих символов, то можно передать в cleanText() третьим параметром массив:
array("\n", "\r", "\t", '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '[', ']',
'{', '}', '~', ',', '.', '?', '<', '>', ';', ':', '"', "'", '\\', '/', '|')


В планах пока сделать так, чтобы пробелы не размножались.
Вот такие пироги smile.gif
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.