2

Say I have 2 variations of a link that get posted on my site...

(the difference is the trailing /)

Once posts are submitted on my site they turn into hyperlinks that look like the following:

<a href="https://vine.co/v/iF20jKHvnqg" target="_blank">https://vine.co/v/iF20jKHvnqg</a>

I have set up a preg replace to capture vine links and convert them into embeds (this post message would contain more obviously but this is for example sake:

$this->post['message'] = '<a href="https://vine.co/v/iF20jKHvnqg" target="_blank">https://vine.co/v/iF20jKHvnqg</a>';

$drc_embed_vine =  '<iframe src="https://vine.co/v/\2/embed/simple" width="480" height="480" frameborder="0"></iframe>';

$this->post['message'] = preg_replace('~(<a href="https?://vine.co)/v/(.*)" target="_blank">(https?://vine.co)/v/(.*)<\/a>~', $drc_embed_vine, $this->post['message']);

I use the wildcard (.*) which I thought meant 'ANYTHING' but for some reason if a link is posted with the trailing slash it doesn't get converted...

I have tried changing my reg ex to (just a couple examples I've tried)

~(<a href="https?://vine.co)/v/(.*)/" target="_blank">(https?://vine.co)/v/(.*)/<\/a>~

which then converts the link with the trailing backslash and ignores the one without.

~(<a href="https?://vine.co)/v/(.*)/?" target="_blank">(https?://vine.co)/v/(.*)/?<\/a>~

which I kinda just thought hey maybe the ? I use for the https check would do the same thing, but did nothing.

then said hey wait thats not in the reg ex so I tried it like

~(<a href="https?://vine.co)/v/(.*/?)" target="_blank">(https?://vine.co)/v/(.*/?)<\/a>~

But still no luck.

How can I make my replace not care if there is a trailing backslash or not?

  • A better usage would be using a parser. You could group the first found URL then check that the value in the `a` is the same with the backreference `\1` or whatever grouping you make it. Parser will be a lot cleaner and less error prone. http://stackoverflow.com/questions/3577641/how-do-you-parse-and-process-html-xml-in-php – chris85 May 11 '16 at 21:24
  • @user6188402 something like `https://vine.co/v/iF20jKHvnqg/` as given for example, I guess – Arcesilas May 11 '16 at 21:25
  • I just asked because I think instead of the _link_, the problem is inside another part of the regex which doesn't match the input – Washington Guedes May 11 '16 at 21:28
  • I also think the problem is the pattern, which cannot match such a link... It took me a moment to figure out what was confusing me – Arcesilas May 11 '16 at 21:29
  • 1
    Also, I'm not sure a regex is necessary in this very case: the result string contains exactly the source string. It's enough to strip the eventual trailing slash and concatenate, or just use sprintf. – Arcesilas May 11 '16 at 21:34
  • @chris85 I have no idea what that means lol, I'm new to all this =/ –  May 12 '16 at 03:31

3 Answers3

1

If you only need this very specific replacement, you can just concatenate strings.

$message = rtrim($post['message'], '/');
$message = sprintf('<iframe src="%s/embed/simple" width="480" height="480" frameborder="0"></iframe>', $message);

Or if you really want to use preg_replace:

$pattern = '~https?://vine.co/v/([^/]+)~';
$this->post['message'] = preg_replace($pattern, $drc_embed_vine, $this->post['message']);

Your pattern need to match the input string ($this->post['message']). Then, put the matching result ($1) in the final string.

To not care for the trailing slash, just consider the video ID will never contain a slash: obviously, it's alphanumerical [a-zA-Z0-9]. We take all characters except the trailing slash with ([^/]+). You could use ([a-z0-9]) with i modifier.

You built a pattern on the final string and trying to match it with the input string.

This script:

<?php
$message = 'https://vine.co/v/iF20jKHvnqg/';

$drc_embed_vine = '<iframe src="https://vine.co/v/\1/embed/simple" width="480" height="480" frameborder="0"></iframe>';

$pattern = '~https?://vine.co/v/([^/]+)/?~';

echo preg_replace($pattern, $drc_embed_vine, $message);

produces this:

<iframe src="https://vine.co/v/iF20jKHvnqg/embed/simple" width="480" height="480" frameborder="0"></iframe>

EDIT

Based on your comment, here is a new pattern, to match the link on the URL submitted:

$pattern = '~^(<[^>]+>)https?://vine.co/v/([^/]+)/?(</a>)$~';

This pattern can match <a href="https://vine.co/v/iF20jKHvnqg" target="_blank">https://vine.co/v/iF20jKHvnqg</a>.

The replace string changes slightly:

'<iframe src="https://vine.co/v/$2/embed/simple" width="480" height="480" frameborder="0"></iframe>'

So I have this test script, which will replace a link as you mention by the iframe:

<?php

$message = '<a href="https://vine.co/v/iF20jKHvnqg" target="_blank">https://vine.co/v/iF20jKHvnqg</a>';

$drc_embed_vine = '<iframe src="https://vine.co/v/$2/embed/simple" width="480" height="480" frameborder="0"></iframe>';

$pattern = '~^(<[^>]+>)https?://vine.co/v/([^/]+)/?(</a>)$~';

echo preg_replace($pattern, $drc_embed_vine, $message);
Arcesilas
  • 1,388
  • 11
  • 24
  • So I failed to mention that my links, once submitted automatically become a hyperlink, I.E. `https://vine.co/v/iF20jKHvnqg` So that would be the message variable, I have added this to the original post. But based on this answer I tinkered with it and came up with `~https?://vine.co/v/([^/]+)/?<\/a>~` for my replace, this didnt work. –  May 12 '16 at 03:07
  • also Im new to regex so I didnt really understand most of that, I just see code and parts of it make sense lol –  May 12 '16 at 03:18
  • 1
    I have also tried `$this->post['message'] = rtrim($this->post['message'], '/');` and also `$post['message'] = rtrim($post['message'], '/');` in the beginning of the plugin but this too didnt work –  May 12 '16 at 03:24
  • So if I understand, user submits a Vine video URL which automatically becomes a link, and it's this link you get and want to transform to a iframe? If I'm right, you don't have full control over user submission: you cannot get the URL, only the link once the URL transformed? What about the trailing slash? Is it also present in the link if user submits a URL with trailing slash? – Arcesilas May 12 '16 at 11:21
  • exactly, if a user posts http://vine.com/v/50471385 thats how the HL will look, if it is with a trailing slash the HL will have a trailing slash. I have tried your code and this does not work for me, the original code I posted works, it just doesnt detect if there is an end slash or not. –  May 12 '16 at 15:34
  • I think what I need to do is remove the trailing slash somehow if the users post includes one, so for example turn `http://vine.co/v/4513544/` to http://vine.co/v/4513544 before doing the preg replace. yeah that would solve it –  May 12 '16 at 15:47
1

Answered in another question I asked, it doesn't ignore the trailing slash but simply removes it all together.

$this->post['message'] = preg_replace('+/(["<])+', '$1', $this->post['message']);

rtrim can not work since / is not the last of the string.

0

Here's a parser example:

$string = '<a href="https://vine.co/v/iF20jKHvnqg" target="_blank">https://vine.co/v/iF20jKHvnqg</a>';
$doc = new DOMDocument();
$doc->loadHTML($string);
$links = $doc->getElementsByTagName('a');
foreach($links as $link) {
    if(preg_match('~^https?://vine\.co/v/([^/]+)~', $link->getAttribute('href'), $url)){
        echo '<iframe src="https://vine.co/v/' . $url[1] . '/embed/simple" width="480" height="480" frameborder="0"></iframe>';
    }
}

Output:

<iframe src="https://vine.co/v/iF20jKHvnqg/embed/simple" width="480" height="480" frameborder="0"></iframe>

Demo: https://eval.in/569642

chris85
  • 23,846
  • 7
  • 34
  • 51