1. '; public static function sanitize(mixed $value): ?string { if ($value === null) { return null; } $html = trim((string) $value); if ($html === '') { return null; } if ($html === strip_tags($html)) { return self::plainToHtml($html); } $clean = trim(strip_tags($html, self::ALLOWED_TAGS)); return $clean === '' ? null : $clean; } public static function normalizeForEditor(?string $value): string { if ($value === null || trim($value) === '') { return ''; } if ($value === strip_tags($value)) { return self::plainToHtml($value) ?? ''; } return $value; } public static function plainToHtml(string $plain): ?string { $plain = str_replace(["\r\n", "\r"], "\n", trim($plain)); if ($plain === '') { return null; } $parts = preg_split("/\n\s*\n/", $plain) ?: []; if (count($parts) === 1 && str_contains($plain, "\n")) { $parts = explode("\n", $plain); } $paragraphs = array_values(array_filter( array_map('trim', $parts), fn (string $part) => $part !== '', )); if ($paragraphs === []) { return null; } return implode('', array_map( fn (string $paragraph) => '

      '.self::escape($paragraph).'

      ', $paragraphs, )); } private static function escape(string $text): string { return htmlspecialchars($text, ENT_QUOTES | ENT_HTML5, 'UTF-8'); } }