Created
August 22, 2023 04:55
-
-
Save smeghead/563e52255bf0a5d11c4d3c12998e1472 to your computer and use it in GitHub Desktop.
テキスト内のURLをタグ化しながら、全体をエスケープするクラス
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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