I want to embed the YouTube video on my website. The problem is with timeline and origin link properties. For example, I have some text and 2 bbCode video tags, one with timeline and 2nd without timeline:
This is just a test example.
[youtube]https://www.youtube.com/watch?v=xHLE2LTAItw&t=53s[/youtube]
[youtube]https://www.youtube.com/watch?v=xHLE2LTAItw[/youtube]
Code:
if (preg_match_all("/\[youtube\]((\s|.)+?)\[\/youtube\]/i", $text, $matches)) {
$allMatches = count($matches[0]);
if (is_array($matches[0]) && $allMatches > 0) {
for ($i = 0; $i < $allMatches; $i++) {
$text = str_replace("watch?v=", "embed/", $text);
if (strpos($matches[0][$i], "&t=") !== false) {
$text = str_replace("&t=", "?start=", $text);
$text = preg_replace("#s\[\/youtube\]#i", "&enablejsapi=1&origin=". HAZELFENCES_WEBSITE ."[/youtube]", $text);
} else {
$text = preg_replace("#\[\/youtube\]#i", "?enablejsapi=1&origin=". HAZELFENCES_WEBSITE ."[/youtube]", $text);
}
}
$text = preg_replace("/\[youtube\]((\s|.)+?)\[\/youtube\]/i", "<iframe width=\"640\" height=\"510\" src=\"\\1\" loading=\"lazy\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>", $text);
}
}
return $text;
The iframe src from the first video returns as: src="https://www.youtube.com/embed/xHLE2LTAItw?start=53&enablejsapi=1&origin=https://test.com?enablejsapi=1&origin=https://test.com" which is wrong. It should be:
https://www.youtube.com/embed/xHLE2LTAItw?start=53&enablejsapi=1&origin=https://test.com
The video link without timeline must be:
https://www.youtube.com/embed/xHLE2LTAItw?enablejsapi=1&origin=https://test.com, which is correct using my code. The only issue is with timeline videos.
Please note, this issue is only occurs when 2 video links are available. One with timeline and the second one without timeline.
For example: https://3v4l.org/JTAUp
Any ideas how to fix it? Thank you.
Ok. It's a bit tricky but I have finally fixed it by using RegExp and preg_replace function. First of all, I have checked for the video link with timeline and then preg_replace the &t=00s[/youtube] with ?start=\\1&enablejsapi=1&origin=". HAZELFENCES_WEBSITE.
Secondly, I checked for the video without timeline and preg_replace the /embed/xHLE2LTAItw[/youtube] with /\\1\\2?enablejsapi=1&origin=". HAZELFENCES_WEBSITE ."[/youtube].
My code:
$text = str_replace("watch?v=", "embed/", $text);
$isVideoWithTimeline = preg_match("#\[youtube\](http|https):\/\/www\.youtube\.com\/([a-z]+\?v=|[a-z]+\/)[a-zA-Z0-9]+(&|&[a-zA-Z]+;)[a-zA-Z]=\d+s\[\/youtube\]#si", $text);
if ($isVideoWithTimeline > 0) {
$text = preg_replace("#&t=([0-9]+)s\[\/youtube\]#si", "?start=\\1&enablejsapi=1&origin=". HAZELFENCES_WEBSITE ."[/youtube]", $text);
}
$isVideoWithoutTimeline = preg_match("#\[youtube\](http|https):\/\/www\.youtube\.com\/([a-z]+\?v=|[a-z]+\/)[a-zA-Z0-9]+\[\/youtube\]#si", $text);
if ($isVideoWithoutTimeline > 0) {
$text = preg_replace("#/([a-z]+\?v=|[a-z]+\/)([a-zA-Z0-9]+)\[\/youtube\]#si", "/\\1\\2?enablejsapi=1&origin=". HAZELFENCES_WEBSITE ."[/youtube]", $text);
}
$text = preg_replace("/\[youtube\]((\s|.)+?)\[\/youtube\]/i", "<iframe width=\"640\" height=\"510\" src=\"\\1\" loading=\"lazy\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>", $text);
return $text;
Now, everything works well. The issue is resolved.
Related
I have a variable as follows:
$post= 'TO UPLOAD DO THIS <img src="Christmas.PNG"> and this <iframe src="https://www.youtube.com/embed/aAkMkVFwAoo"></iframe>';
With the <img> tag I want to process the image to display diferently. I also want the video to be processed differently (customisable). I have done the following:
//Image processing:
preg_match_all('/<img src=\"(.*?)\">/',$post,$matches);
if(sizeof($matches[1])>0){
$toRmove=[];
$toAdd = [];
foreach($matches[1] as $m){
$value = $m;
$toRemove[]='<img src="'.$value.'">';
$toAdd[]='<img src="images/'.$value.'" width=20% height=20%>';
}
$new_message = str_replace($toRemove,$toAdd,$post);
$post= $new_message;
}
//video processing
preg_match_all('/<iframe src=\"(.*?)\">/',$post,$matches);
if(sizeof($matches[1])>0){
$toRmove=[];
$toAdd = [];
foreach($matches[1] as $m){
$value = $m;
$toRemove[] ='<iframe src="'.$value.'">';
$toAdd[] ='<iframe width="560" height="315" src="https://www.youtube.com/embed/aAkMkVFwAoo" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen>';
}
$new_message = str_replace($toRemove,$toAdd,$post);
$post= $new_message;
}
echo $post;
When I echo $toAdd[0], the video displays correctly with what i want. However, after the str_replace($toRemove,$toAdd,$post); and then i echo $post the video just disappears but the image is still there and displaying correctly.
So the video processing is working but when it i go to add it, the video doesn't appear just blank.
Why is this occurring? Thanks.
I'm trying to turn youtube links into embed iframes, to play the videos. However, my current code is replacing the entire sentence with the embed code. What I want to do is to just convert the youtube link to an embed code, and leave the rest of the text unharmed.
Example: This is a youtube link: https://www.youtube.com/watch?v=T-8XurAKMkU and some text after.
Turned into: This is a youtube link: <embed> and some text after.
My current code:
$testing = "This is a youtube link: https://www.youtube.com/watch?v=T-8XurAKMkU and some text after.";
echo $core->convertyoutube($testing);
And the function:
public function convertyoutube($link) {
if (strpos($link, 'youtube.com/watch?v=') == true) {
$url = $link;
parse_str(parse_url($url, PHP_URL_QUERY), $youtube_array);
$videoid = $youtube_array['v'];
$embed = "<iframe width='420' height='315' src='https://www.youtube.com/embed/".$videoid."'></iframe>"; // what it should create with the extracted code
return $embed;
}
}
Well You are returning only embed code:
return $embed;
You need to replace only youtube part:
public function convertyoutube($link) {
$position = strpos($link, 'youtube.com/watch?v=');
if ($position !== false) {
$chunks = explode(' ', $link);
foreach ($chunks as &$chunk) {
$isYoutubeLink = strpos($chunk, 'youtube.com/watch?v=');
if ($isYoutubeLink !== false) {
$url = $chunk;
parse_str(parse_url($url, PHP_URL_QUERY), $youtube_array);
$videoid = $youtube_array['v'];
$chunk = "<iframe width='420' height='315' src='https://www.youtube.com/embed/".$videoid."'></iframe>"; // what it should create with the extracted code
}
}
return implode(' ', $chunks);
}
}
It works with multiple links in sentence. I guess there is "better" way with using regexp, however I am not very good at regexp and don't like to use it where it is not mandatory.
You could actually do this all with a single regex.
echo preg_replace('/https?:\/\/(?:www\.)?youtube\.com\/watch\?v=(.+?)(?:&|\s|$)/',
'<iframe width="420" height="315" src="https://www.youtube.com/embed/$1"></iframe>',
'This is a youtube link: https://www.youtube.com/watch?v=T-8XurAKMkU and some text after.');
Output:
This is a youtube link: https://www.youtube.com/watch?v=T-8XurAKMkU and some text after.
Regex101 Demo: https://regex101.com/r/cT2mW1/2
It will be better if you convert the links at the front-end view with javascript to avoid a excess loading of server. But it's your choise.
Single youtube video has different links like these:
1) https://www.youtube.com/watch?v=lfKON5AMvTM
2) https://youtu.be/lfKON5AMvTM
For this reason you should write your codes like this to catch every type of youtube links:
public function convertYouTube($content) {
$content = preg_replace("/http(s)?:\/\/youtu\.be\/([^\40\t\r\n\<]+)/i", '<iframe width="420" height="315" src="https://www.youtube.com/embed/$2"></iframe>', $content);
$content = preg_replace("/http(s)?:\/\/(w{3}\.)?youtube\.com\/watch\/?\?v=([^\40\t\r\n\<]+)/i", '<iframe width="420" height="315" src="https://www.youtube.com/embed/$3"></iframe>', $content);
return $content;
}
I have functions that change links into clickable links and one that changes youtube links into embedded videos.
However, if you post a youtube video first then a regular link, all links turn into youtube videos.
How can I edit my functions to only change youtube links into embedded videos and ignore regular links?
function convertLinks($Link) {
$Link = preg_replace(
"#(^|[\n ])([\w]+?://[\w]+[^ \"\n\r\t< ]*)#",
"\\1\\2",
$Link);
$Link = preg_replace(
"#(^|[\n ])((www|ftp)\.[^ \"\t\n\r< ]*)#",
"\\1\\2",
$Link);
return $Link;
}
function convertYouTube($Link) {
if (preg_match(
'%(?:youtube(?:-nocookie)?\.com/(?:[^/]+/.+/|(?:v|e(?:mbed)?)/|.*[?&]v=)|youtu\.be/)([^"&?/ ]{11})%i',
$Link,
$match)) {
$video_id = $match[1];
$Link = htmlspecialchars_decode(
preg_replace(
"#(^|[\n ])([\w]+?://[\w]+[^ \"\n\r\t< ]*)#",
"\\1<iframe width=\"640\" height=\"360\" src=\"http://www.youtube.com/embed/$video_id\" frameborder=\"0\" allowfullscreen></iframe>",
$Link));
}
return $Link;
}
function convertMessages($Comment) {
$Comment = convertYouTube($Comment);
$Comment = convertLinks($Comment);
return $Comment;
}
I think I see where ukautz is coming from; you're finding certain youtube-only link text in your preg_match, yet in your preg_replace your regex doesn't care about youtube-specific text. If you were somehow able to isolate out the links before preg_matching them, this should solve the problem; however an easier solution might be to just combine your preg_match regex with your preg_replace regex.
i have a posting feature on my site that can embed links and youtube videos. the problem is, that the two clash together, and the youtube iframe ends up being a 404 page on my site. my codes for the youtube videos and links are below, but im not sure how to stop them from combining and ruining it.
by combining, i mean this http://www.youtube.com/watch?v=VhqiT2nWCVU turns to
<iframe src="http://www.youtube.com/watch?v=VhqiT2nWCVU">
which then turns into
<iframe src="">
sorry if i am unclear in any way. my codes are below.
function youtube($string)
{
return preg_replace(
'#(http://(www.)?youtube.com)?/(v/|watch\?v\=)([-|~_0-9A-Za-z]+)&?.*?#i',
'<iframe title="YouTube video player" width="480" height="390" src="http://www.youtube.com/embed/$4?rel=0" frameborder="0" allowfullscreen></iframe>',
$string
);
}
$posted = youtube($posted);
$rexProtocol = '(https?://)?';
$rexDomain = '((?:[-a-zA-Z0-9]{1,63}\.)+[-a-zA-Z0-9]{2,63}|(?:[0-9]{1,3}\.){3}[0-9]{1,3})';
$rexPort = '(:[0-9]{1,5})?';
$rexPath = '(/[!$-/0-9:;=#_\':;!a-zA-Z\x7f-\xff]*?)?';
$rexQuery = '(\?[!$-/0-9:;=#_\':;!a-zA-Z\x7f-\xff]+?)?';
$rexFragment = '(#[!$-/0-9:;=#_\':;!a-zA-Z\x7f-\xff]+?)?';
// Solution 1:
function callback($match)
{
// Prepend http:// if no protocol specified
$completeUrl = $match[1] ? $match[0] : "http://{$match[0]}";
return '<a href="' . $completeUrl . '">'
. $match[2] . $match[3] . $match[4] . '</a>';
}
$posted = preg_replace_callback("&\\b$rexProtocol$rexDomain$rexPort$rexPath$rexQuery$rexFragment(?=[?.!,;:\"]?(\s|$))&",
'callback', $posted);
A popular solution to this problem is to use placeholders. On your first pass you turn all YouTube links into a placeholder, for example:
{{youtube:VhqiT2nWCVU}}
After that you run your normal link converter. And at the end your run yet another regex to turn all your palceholders into youtube embeds.
Well this is the function which active the link if someone put a link in message box with text.
My question is it doesn't show more than 1 link if someone put many link ex: www.yahoo.com www.gmail.com www.facebook.com, Then it's show only first link www.yahoo.com
function txt2link($text){
// force http: on www.
$text = ereg_replace( "www\.", "http://www.", $text );
// eliminate duplicates after force
$text = ereg_replace( "http://http://www\.", "http://www.", $text );
$text = ereg_replace( "https://http://www\.", "https://www.", $text );
// The Regular Expression filter
$reg_exUrl = "/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/";
// Check if there is a url in the text
if(preg_match($reg_exUrl, $text, $url)) {
// make the urls hyper links
$text = preg_replace($reg_exUrl, ''.$url[0].'', $text);
} // if no urls in the text just return the text
return ($text);
}
$url = "Alter pot waer it your pot http://css-tricks.com/snippets/php/find-urls-in-
text-make-links/ you may click the link www.yahoo.com or you may see what is the
http://www.youtube.com say, is it right?";
echo txt2link($url);
you can run this code to see the result.
Any Idea ?
This is one that someone here helped me build up a while back, I dunno where it is on stack anymore but I still use this function to date.. This handles many urls in one shot, with or without http: with or without www. in most cases, its true this could us a bit of refining, but in all does the job really nice.
//for finding URLs within body of text and converting them to a clickable link
//checks DNS to see if its valid and if the link HTML already exists ignores it.
function titleHyper($text){
$text = preg_replace( "/(www\.)/is", "http://", $text);
$text = str_replace(array("http://http://","http://https://"), "http://", $text);
$text = str_replace(array("<a href='", "<a href=\"", "</a>", "'>", "\">"), "", $text);
$reg_exUrl = "/(http|https|ftp|ftps|)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/";
preg_match_all($reg_exUrl, $text, $matches);
$usedPatterns = array();
$context = stream_context_create(array(
'http' => array(
'timeout' => 5
)
));
foreach($matches[0] as $pattern){
if(!array_key_exists($pattern, $usedPatterns)){
$usedPatterns[$pattern]=true;
$the_contents = #file_get_contents($pattern, 0, $context);
if(substr(trim($pattern), 0, 8) != "https://"){
$color = "#FF0000";
}
if (empty($the_contents)) {
$title = $pattern;
} else {
preg_match("/<title>(.*)<\/title>/Umis", $the_contents, $title);
$title = $title[1];
$color = "#00FF00";
//$title = htmlspecialchars($title, ENT_QUOTES); //saving data to database
}
$text = str_ireplace($pattern, "<a style='font-size: 14px; background-color: #FFFFFF; color: $color;' href='$pattern' rel='nofollow' TARGET='_blank'> $title </a>", $text);
}
}
return $text;
}
// titleHyper() in action example:
//$text = "Some sample text with WWW.AOL.com<br />http://www.youtube.com/watch?v=YaxKiZfQcX8 <br />Anyone use www.myspace.com? <br />Some people are nuts, look at this stargate link at http://www.youtube.com/watch?v=ZKoUm6z5SzU&feature=grec_index , like aliens exist or something. http://www.youtube.com/watch?v=sfN-7HczmOU&feature=grec_index and here's a secure site https://familyhistory.hhs.gov, unless you use curl or allow secure connections it will never get a title. <br /> This is a not valid site http://zzzzzzz and this is a dead site http://zwzwzwxzw.com.<br /> Lastly lets try an already made hyperlink and see what it does <a href='http://tacobell.com'>taco bell</a>";
//echo titleHyper($text);