0

I'm using preg_replace with an array to go through my bbcode and make the change when a news entry is posted.

For example

$bbcode = array (
    "/\[url\=(.*?)\](.*?)\[\/url\]/is" => "<a href='$1' target='_blank'>$2</a>"
);

So then when I pull data from the database (in this example $newsPost) which contains the text and bbcode, I do this.

$newsPost  = preg_replace(array_keys($bbcode), array_values($bbcode), $newsPost);

Now, what I'd like is to find out if the value of $1 contains my domain, the target should be "top" and if not, it should be blank.

So if we have [url=http://www.mydomain.com]visit our page[/url]. then it's transformed to <a href="http://www.mydomain.com" target="top">visit our page</a> and anything else will have target="_blank".

Any ideas?

Thanks in advance!

1 Answer 1

1

EDITED/FIXED

  • Added str_replace() to deal with dots in domain names
  • Initially I fixed your backslashes (if you want a literal backslash in your Regex it should be \\ in the string) but I have undone this as you have said it was working for you in the first place.

How about this?

$mydomain = 'domain.tld';
$bbcode = array (
  "/\[url\=([^]]*)(".str_replace('.','\\.',$mydomain).")([^]]*)\]([^[]*)\[\/url\]/is" => "<a href='$1$2$3' target='top'>$4</a>",
  "/\[url\]([^[]*)(".str_replace('.','\\.',$mydomain).")([^[]*)\[\/url\]/is" => "<a href='$1$2$3' target='top'>$1$2$3</a>";
  "/\[url\=([^]]*)\]([^[]*)\[\/url]/is" => "<a href='$1' target='_blank'>$2</a>"
  "/\[url\]([^[]*)\[\/url\]/is" => "<a href='$1' target='_blank'>$1</a>",
);

If that will work for you, a caveat: Don't set $mydomain to www.domain.tld, set it to domain.tld, so you catch all subdomains.

You could even do it with multiple domains like this:

$mydomains = array(
  'domain.tld',
  'anotherdomain.tld',
  'sub.yetanotherdomain.tld'
);

// Add domain-specific rules before general rules so we don't match domain
// specific links with the general link rule (we have replaced them by that point)
$domainrules = array();
foreach ($mydomains as $domain) {
  $domainrules["/\[url\=([^]]*)(".str_replace('.','\\.',$domain).")([^]]*)\]([^[]*)\[\/url\]/is"] = "<a href='$1$2$3' target='top'>$4</a>";
  $domainrules["/\[url\]([^[]*)(".str_replace('.','\\.',$domain).")([^[]*)\[\/url\]/is"] = "<a href='$1$2$3' target='top'>$1$2$3</a>";
}

// This array contains all your static BBCode rules
$staticrules = array(
  "/\[url\=([^]]*)\]([^[]*)\[\/url\]/is" => "<a href='$1' target='_blank'>$2</a>",
  "/\[url\]([^[]*)\[\/url\]/is" => "<a href='$1' target='_blank'>$1</a>",
  "/\[b\]([^[]*)\[\/b\]/is" => "<span class='bold_text'>$1</span>",
  ...
);

// Make an array that contains all the rules
$bbcode = array_merge($staticrules,$domainrules);
Sign up to request clarification or add additional context in comments.

7 Comments

Worked perfectly! Thank you. A little unsure about the second example. If I have a lot of items in bbcode (20+), I'd have to rewrite each to fit the $bbcode[] style?
@scatteredbomb No, you can use array_merge(), see my updated answer
@scatteredbomb just edited again, I just realised you will need to account for people using [url]http://my.url/[/url] syntax, as well as [url=http://my.url/]some text[/url]
@scatteredbomb You are leaving yourself open to XSS attacks with this, you could do with adding a rule that will disallow any links that start with javascript:, for example you could convert them to <span class="illegal_link">This link is not allowed and was blocked<span>.
I did wonder if you might have that problem, what you will have to do is use a negated character class (like [^]]*) instead of .*? to match the data fields you want. See updated answer. Also, you might be interested in RegExr for playing around with it and seeing exactly what it matches.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.