I'm looking to write a shortcode system for a gaming community/database where users can add something like ((Magical Sword))
to their content and it will be parsed as Beautiful links to related items with inline thumbnails.
This is the code I'm using so far:
function inlineItems($text) { $re = "/\(\(([^)]+)\)\)/m"; preg_match_all($re, $text, $matches, PREG_SET_ORDER, 0); foreach($matches as $match) { $slug = makeSlug($match[1]); $item = getItem($slug); if($item) { $text = preg_replace($match[0], '<a class="text-item" data-tooltip="tooltip-item-' . $item->slug . '" href="/items/' . $item->slug .'"><img src="/images/items/' . $item->slug .'.png">' . $item->name .'</a>', $text); } } $text = str_replace("((", "", $text); $text = str_replace("))", "", $text); return $text; }
Example output, if the user entered ((Crystal Sword))
would be:
<a class="text-item" data-tooltip="tooltip-item-crystal-sword" href="/items/crystal-sword"><img src="/images/items/crystal-sword.png">Crystal Sword</a>
So far so good, so good.
However, problems arise when a specific match is repeated multiple times within a text string.
If the user enters something like: A ((Crystal Sword)) is crucial for farming, get one ((Crystal Sword)) as soon as possible. ((Crystal Sword)) is the best!
Then replace multiple matching project names, and you will end up with this confusion:
<a class="text-item" data-tooltip="tooltip-item-crystal-sword" href="/items/crystal-sword"><img src="/images/items/crystal-sword.png"></a><a class="text-item" data-tooltip="tooltip-item-crystal-sword" href="/items/crystal-sword"><img src="/images/items/crystal-sword.png"></a><a class="text-item" data-tooltip="tooltip-item-crystal-sword" href="/items/crystal-sword"><img src="/images/items/crystal-sword.png">Crystal Sword</a>
How to prevent it from overlapping matches like this?
Your code is quite confusing. You don't need all of these replacements, one is enough. Follow the KISS principle: