API Twitteru v exportech nabízí tzv. entity – informace o aktivních částech textu, např. o URL adresách, uživatelích nebo haších. Aktivní části jsou označeny pomocí pozice svého začátku a konce. Jak postupovat, když chceme z textového tvítu vytvořit HTML kód s odkazy na jednotlivé entity?
Při přímočarém přístupu (bereme jednotlivé entity a postupně je nahrazujeme) samozřejmě narazíme hned u dvou entit – nahrazením původního textu vznikne delší text, takže se změní původní pozice. Nabízelo by se postupovat odzadu, to je ale taky problematické: entit je více druhů, takže bychom nejprve museli projít všechny, seřadit je do jednoho pole a zpracovat teprve to. Zásadní problém je ale v něčem jiném: tvíty obsahují běžný text, takže je před vytvořením HTML kódu musíme ošetřit funkcí htmlspecialchars – nemůžeme to udělat před nahrazením entit (protože by se změnily pozice) a nemůžeme to udělat ani potom (protože by se ošetřily i vytvořené odkazy). K problému bude potřeba přistoupit jinak.
Elegantní řešení spočívá v tom, že si text rozdělíme na jednotlivé znaky a pracujeme s nimi:
<?php /** Vytvoří HTML kód s dosazenými URL adresami * @param string čistý text v UTF-8 * @param array obsahuje pole array("start" => , "end" => , "url" => , "display_url" => ) * @return string HTML * @copyright Jakub Vrána, https://php.vrana.cz/ */ function html_urls($text, $urls) { $fragments = preg_split('~~u', $text, -1, PREG_SPLIT_NO_EMPTY); $fragments = array_map('htmlspecialchars', $fragments); foreach ($urls as $url) { $length = $url["end"] - $url["start"]; $link = '<a href="' . htmlspecialchars($url["url"]) . '">' . htmlspecialchars($url["display_url"]) . '</a>'; array_splice($fragments, $url["start"], $length, array($link) + array_fill(0, $length, "")); } return implode($fragments); } ?>
Pro nahrazení části pole se používá funkce array_splice. Předáváme jí stejně dlouhé pole jako nahrazujeme (vytvořené pomocí array_fill(0, $length, "")
), abychom neporušili nahrazení dalších entit.
Diskuse je zrušena z důvodu spamu.