Skip to content

Instantly share code, notes, and snippets.

@smeghead
Created August 22, 2023 04:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save smeghead/563e52255bf0a5d11c4d3c12998e1472 to your computer and use it in GitHub Desktop.
Save smeghead/563e52255bf0a5d11c4d3c12998e1472 to your computer and use it in GitHub Desktop.
テキスト内のURLをタグ化しながら、全体をエスケープするクラス
<?php declare(strict_types=1);
namespace Domain;
/**
* URLを含むテキストをエスケープする。
* URLはリンクとして出力します。
* 改行は<br>を出力します。
*/
final class HyperLinkText {
private string $text;
public function __construct(?string $text) {
$this->text = strval($text);
}
public function h(): string {
$lines = preg_split('/\r?\n/', $this->text);
$outputLines = [];
foreach ($lines as $line) {
if (preg_match_all('/https?:\/{2}[\w\/:%#\$&\?\(\)~\.=\+\-]+/', $line, $matches)) {
try {
$restText = $line;
$parts = [];
foreach ($matches[0] as $url) {
$position = mb_strpos($restText, $url);
if ($position === false) {
throw new \Exception('failed to search url string.');
}
// URLより前の部分をエスケープしてpartsに格納する。
$parts[] = htmlspecialchars(mb_substr($restText, 0, $position), ENT_QUOTES);
// URLをリンクに変換する。
$parts[] = sprintf(
'<a href="%s" target="_blank" rel="noopener">%s</a>',
htmlspecialchars($url, ENT_QUOTES),
htmlspecialchars($url, ENT_QUOTES)
);
$restText = mb_substr($restText, $position + mb_strlen($url));
}
// 残りをエスケープして格納する。
$parts[] = htmlspecialchars($restText, ENT_QUOTES);
$outputLines[] = implode('', $parts);
} catch (\Exception $e) {
$outputLines[] = htmlspecialchars($line, ENT_QUOTES); // 例外が発生した場合は、タグ化を諦めてエスケープした文字列を表示する。
}
} else {
$outputLines[] = htmlspecialchars($line, ENT_QUOTES);
}
}
return implode("<br>\n", $outputLines);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment