Re: 유튜브, 트위터 임베딩 관련 autolink 함수 수정판 백업
⚠️꼭 백업하고 진행하세요⚠️
lib/board_common.lib.php
function autolink($text, $bo_table = '')
{
// 1. 태그 보호 (코드 블록 및 주요 HTML 태그)
$placeholders = array();
$placeholder_index = 0;
// 니코동 및 GIST 임베드 스크립트 골라서 보호
$text = preg_replace_callback('/<script[^>]+src="(?:https:\/\/embed\.nicovideo\.jp\/|https:\/\/gist\.github\.com\/)[^>]+><\/script>/is', function ($matches) use (&$placeholders, &$placeholder_index) {
$key = "___PROTECT_BLOCK_{$placeholder_index}___";
$placeholders[$key] = $matches[0];
$placeholder_index++;
return $key;
}, $text);
// 기존의 안전한 태그들(pre, code 등)도 이어서 보호
$safe_patterns = [
'/<pre[^>]*>.*?<\/pre>/is',
'/<code[^>]*>.*?<\/code>/is',
'/<a[^>]*>.*?<\/a>/is',
'/<img[^>]*>/is',
'/<iframe[^>]*>.*?<\/iframe>/is'
];
foreach ($safe_patterns as $pattern) {
$text = preg_replace_callback($pattern, function ($matches) use (&$placeholders, &$placeholder_index) {
$key = "___PROTECT_BLOCK_{$placeholder_index}___";
$placeholders[$key] = $matches[0];
$placeholder_index++;
return $key;
}, $text);
}
// 1. 비디오 렌더링 공통 로직 (유튜브 + 동영상 파일)
$get_video_render = function ($url) {
$url = trim($url);
// 1-1. 유튜브 체크
$yt_pattern = '/(?:youtu\.be\/|youtube\.com\/(?:watch\?v=|embed\/|shorts\/))([a-zA-Z0-9_-]+)/i';
if (preg_match($yt_pattern, $url, $match)) {
return '<div class="auto_link_video"><iframe src="https://www.youtube.com/embed/' . $match[1] . '" frameborder="0" allowfullscreen></iframe></div>';
}
// 1-2. 일반 동영상 파일 체크 (mp4, webm, ogv)
if (preg_match('/\.(mp4|webm|ogv)$/i', $url)) {
$ext = pathinfo($url, PATHINFO_EXTENSION);
return '<div class="auto_link_video_wrapper">
<video controls preload="metadata" style="width: 100%; max-height: 500px; background: #000;">
<source src="' . $url . '" type="video/' . $ext . '">
브라우저가 비디오 태그를 지원하지 않습니다. <a href="' . $url . '">파일 다운로드</a>
</video>
</div>';
}
return null;
};
// 2. 비디오[URL] 패턴 처리 (사용자가 명시적으로 입력한 경우)
$text = preg_replace_callback('/비디오\[(https?:\/\/[^\]]+)\]/i', function ($matches) use ($get_video_render) {
$url = $matches[1];
$render = $get_video_render($url);
return $render ? $render : '비디오 링크 오류 또는 지원하지 않는 형식입니다.';
}, $text);
// 3. 이미지[URL] 패턴 처리 (이미 <a>로 보호된 경우 제외하고 텍스트 형태일 때)
$text = preg_replace_callback('/\[\s*(https?:\/\/[^\]]+)\s*\]/i', function ($matches) {
$url = $matches[1];
// 트위터/X 이미지 처리 등 특정 조건이 필요하면 여기서 분기
return '<img src="' . $url . '" class="auto_link_image" alt="image" style="max-width: 100%; height: auto;">';
}, $text);
// 4. 트위터/X 임베드 처리
$text = preg_replace_callback(
'/https?:\/\/(?:www\.)?(?:twitter\.com|x\.com)\/[A-Za-z0-9_]+\/status\/([0-9]+)(?:\?[^\s<>"',]*)?(?:,(m))?/i',
function ($matches) {
$tweet_id = $matches[1];
$is_video_mode = isset($matches[2]) && strtolower($matches[2]) === 'm';
// 1. 기본 속성 설정
$data_attr = 'data-width="500" data-lang="ko"';
// 2. ,m 이 붙었을 경우 영상 최적화 속성 추가
if ($is_video_mode) {
$data_attr .= ' data-media-max-width="560"';
}
// 3. 공식 blockquote 구조 생성
$html = '<blockquote class="twitter-tweet" ' . $data_attr . ' style="margin: 10px auto;">';
$html .= '<a href="https://twitter.com/i/status/' . $tweet_id . '"></a>';
$html .= '</blockquote>';
return $html;
},
$text
);
// 5. 링크[URL] 패턴 (OG 카드)
$text = preg_replace_callback('/링크\[(https?:\/\/[^\]]+)\]/i', function ($matches) {
$url = trim($matches[1]);
if (function_exists('fetch_og_metadata') && $og = fetch_og_metadata($url)) {
return render_link_card($url, $og);
}
return '<a href="' . htmlspecialchars($url, ENT_QUOTES) . '" class="auto_link" target="_blank" rel="noopener noreferrer">' . htmlspecialchars($url, ENT_QUOTES) . '</a>';
}, $text);
// 6. 일반 URL 패턴 처리
$text = preg_replace_callback('/https?:\/\/[^\s<>"']+/i', function ($matches) use ($get_video_render) {
$url = $matches[0];
// 비디오/유튜브 통합 체크
if ($video_html = $get_video_render($url)) {
return $video_html;
}
// 트위터/X URL 체크 (패스)
if (preg_match('/(?:twitter\.com|x\.com)\/[A-Za-z0-9_]+\/status\/[0-9]+/i', $url)) {
return $url;
}
// 이미지 체크
if (preg_match('/\.(jpg|jpeg|png|gif|webp)$/i', $url)) {
return '<img src="' . $url . '" class="auto_link_image" alt="image" style="max-width: 100%; height: auto;">';
}
// 일반 링크
return '<a href="' . $url . '" class="auto_link" target="_blank" rel="noopener noreferrer">URL</a>';
}, $text);
// 7. 해시태그 처리
$parts = preg_split('/(____PROTECT_BLOCK_\d+____|<[^>]+>)/s', $text, -1, PREG_SPLIT_DELIM_CAPTURE);
foreach ($parts as &$part) {
if (!preg_match('/^____PROTECT_BLOCK_/', $part) && strpos($part, '<') !== 0) {
$part = preg_replace_callback('/#([가-힣a-zA-Z][^\s#<>]*)/u', function ($matches) use ($bo_table) {
$tag = $matches[1];
$clean_tag = preg_replace('/[;\!\?\.\,\)\]]+$/', '', $tag);
if (preg_match('/^[0-9a-fA-F]{3,8}$/', $clean_tag) || preg_match('/^\d+/', $clean_tag)) {
return '#' . $tag;
}
$link = G5_BBS_URL . '/board.php?bo_table=' . $bo_table . '&hash=' . urlencode($tag);
return '<a href="' . $link . '" class="hashtag">#' . $tag . '</a>';
}, $part);
}
}
$text = implode('', $parts);
// 8. 보호된 블록 복원 (역순으로 복원하여 중첩 방지)
$placeholders = array_reverse($placeholders, true);
foreach ($placeholders as $key => $original) {
$text = str_replace($key, $original, $text);
}
return $text;
}- 이전글트위터 URL로 임베드하기 26.03.09
- 다음글트위터 URL로 동영상만 임베드하기 (v1.7.0 대응) 26.06.02
댓글목록
댓글
니루 @tabom0w0