BB kód v PHP
Formátování příspěvků pomocí BB code v PHP. Převod BB kódu do HTML.
V případě, že chceme umožnit návštěvníkům stránky používat základní formátování textu, existuje několik základních způsobů, jak to zařídit.
- WYSIWYG editor,
- HTML značky,
- Markdown/Texy!,
- BB code
Každá z možností má své pro a proti.
Co to je BB code?
Stručně řečeno má BB kód zjednodušenou podobu HTML kódu, kdy se místo špičatých <>
závorek zapisují hranaté []
(tyto znaky lze relativně pohodlně zapsat i na české klávesnici).
Zkratka BB znamená Bulletin Board, protože se tento způsob formátování nejvíce rozšířil na diskusních fórech.
Základní znaky
Typické BB značky:
BB kód | HTML ekvivalent | Výsledek |
---|---|---|
[b]text[/b] |
<b>text</b> |
text |
[i]text[/i] |
<i>text</i> |
text |
[code]code[/code] |
<code>text</code> |
text |
[url=http://example.com]text[/url] |
<a href='http://example.com'>text</a> |
text |
[img]http://example.com/obrazek.png[/img] |
<img src='http://example.com/obrazek.png'>text</a> |
(obrázek) |
Asi hlavní výhoda oproti obyčejnému HTML spočívá v tom, že:
- Není problém zapsat ukázku HTML kódu. HTML se neinterpretuje a zároveň nezahodí, ale převede na entity.
- V PHP není jednoduchý způsob, jak povolit jen určité HTML značky a atributy. Značky zvládne sice odstranit funkce
strip_tags
, ale na povolení atributů je potřeba nějaký nástroj jako HTML Purifier.
Převod BB značek na HTML
Jednoduché značky [b]
, [i]
, [code]
Nejjednodušší způsob jako převádět [b]text[/b]
na ><b>text</b>
a podobně je použití regulárních výrazů a funkce preg_replace
.
$text = preg_replace(
"~\[(b)\](.+?)\[/\\1\]~ui",
"<\\1>\\2</\\1>",
$text
);
Formátování všech jednoduchých značek ([b]
, [i]
, [code]
) může zajistit jednoduchá funkce, které se předají požadované značky.
function obycejnyBbKod($znacky, $text) {
foreach ($znacky as $znacka) {
$text = preg_replace(
"~\[($znacka)\](.+?)\[/\\1\]~ui",
"<\\1>\\2</\\1>",
$text
);
}
return $text;
}
Použití.
$text = obycejnyBbKod(
array("b", "i", "code"), $text
);
echo $text;
Značka [img]
V případě vkládání obrázků je nutné vytvořit jinou funkci (už se nebude nahrazovat značka za značku, ale potřebujeme obsah mezi [img]
a [/img]
dostat do src
atributu značky <img>
). Regulární výraz ale bude stejný.
$text = preg_replace(
"~\[img\](.+?)\[/img]~ui",
"<img src='\\1'>",
$text
);
Složitější BB značky [url]
BB značky, kde může být nějaký atribut s hodnotou, musí zpracovávat trochu složitější regulární výraz.
$text = preg_replace(
"~\[url=(.+?)\](.+?)\[/url]~ui",
"<a href='\\1'>\\2</a>",
$text
);
Bezpečnost
Je potřeba myslet na to, že vstup od uživatele je nutno chránit před XSS a zároveň veškeré akce chránit před CSRF. Možnost vložit obrázek může být skvělá příležitost, jak administrátor načte požadovanou URL (třeba URL pro smazání obsahu), aniž by o tom věděl.
XSS
Proti XSS je vhodný postup ošetřit před převáděním na BB code obsah funkcí htmlspecialchars
.
$text = htmlspecialchars($text, ENT_QUOTES);
Uvést druhý parametr ENT_QUOTES
je naprosto klíčové. Zabrání to možnosti vložit škodlivý kód typu:
[img]http://example.com' onclick='alert("XSS")[/img]
Který by se jinak přetvořil na validní, funkční a nebezpečný kód:
<img src='http://example.com' onclick='alert("XSS")'>
Zpracovávání obsahu značek
V případě, že je žádoucí zadaný obsah BB značek nějak zpracovávat (upravovat), poslouží k tomu PHP funkce preg_replace_callback
.
$text = preg_replace_callback(
"~\[url=(.+?)\](.+?)\[/url]~ui",
function($vyskyty) {
$cilOdkazu = $vyskyty["1"];
$textOdkazu = $vyskyty["2"];
// nějaké operace
return "<a href='" . $cilOdkazu . "'>" . $textOdkazu . "</a>";
},
$text
);
Hotové řešení
Hotové řešení BB code v PHP je na GitHubu.
Zpětný převod HTML na BB code
Převádět pro účely editace textů v BB kódu zpětně z HTML sice možné je, ale není to úplně ideální postup. Musí se kromě funkcí „BB Code → HTML“ vytvářet i převody opačné.
Navíc to není jen dopisování zpětných regulárních výrazů. Když se rozhodneme, že HTML značky obrázků mají mít třeba nějakou třídu, bude se muset psát další regulární výraz pro převod staré podoby HTML do nové. Nebo si napsat nějaký skript, co všechen obsah dekóduje do BB a převede zpět do nové podoby HTML.
Většinou lepší řešení je ukládat v DB obě podoby – jednu v BB kódu pro editaci a druhou v HTML pro výpis. Převádět BB kód by sice bylo možné při každém vypsání stránky, ale je to trochu zbytečná zátěž.
Problémy
Převody BB značek na HTML regulárními výrazy nejsou úplně neprůstřelné. Například není problém vytvořit překřížené značky a obecně nevalidní výstup. Je to ale řešení na pár řádek, což by napsání dokonale funkčního parseru, který by těmito problémy netrpěl, nebylo.
Komentáře