Joomla 3内容插件:Foreach preg_replace $ row->全文重复第一个字符串

I am setting up a new content plugin for Joomla 3, that should replace plugin tags with html content. Everything works fine till the moment when i am preg_replace plugin tags in $row->fulltext.

Here is the plugin code

public function onContentPrepare($context, &$row, &$params, $page = 0) {
$pattern = '#\{uni\}(.*){\/uni\}#sU';
    preg_match_all($pattern, $row->fulltext, $matches,  PREG_PATTERN_ORDER);

    foreach($matches[1] as $k=>$uni){

        preg_match('/\{uni-title\}(.*)[\{]/Ui', $uni, $unititle);
        preg_match('/\{uni-text\}(.*)/si', $uni, $unitext);

        $titleID = str_replace(' ', '_', trim($unititle[1]));

        $newString = '<span id="'.$titleID.'">'.$unititle[1].'</span><div class="university-info-holder"><div class="university-info"><i class="icon icon-close"></i>'.$unitext[1].'</div></div>';

        $row->fulltext = preg_replace($pattern,$newString,$row->fulltext);

    }
}

Any ideas, why it duplicates first found match, as many times as foreach goes?

Just to mention, if i do:

echo $unititle[1];

inside foreach, items aren't duplicated, but are rendered as it should be.

There are a few problems with the original code.

  1. It should be using $row->text instead of $row->fulltext. This is because when rendering an article Joomla merges tht introtext and fulltext fields.

  2. It's a mistake to use $pattern for the matching when making the substitution. That's because the $pattern matches all of the items. Instead use the $match[0][$k] to do the replacement. Use str_replace instead of preg_replace because now you are matching the exact string and don't need to do a regex. Here's the code for the whole thing.

    class PlgContentLivefilter extends JPlugin{ public function onContentPrepare($context, &$row, &$params, $page = 0) { return $renderUniInfo = $this->renderUniInfo($row, $params, $page = 0);
    }

    private function renderUniInfo(&$row, &$params, $page = 0) {

        $pattern = '#\{uni\}(.*){\/uni\}#sU';
    
        preg_match_all($pattern, $row->text, $matches);
    
        foreach($matches[0] as $k=>$uni){
    
    
    
                preg_match('/\{uni-title\}(.*)[\{]/Ui', $uni, $unititle);
                preg_match('/\{uni-text\}(.*)/si', $uni, $unitext);
    
                print_r($unititle[1]);
    
                $title = $unititle[1];
                $text = $unitext[1];
    
                if (preg_match('#(?:http://)?(?:https://)?(?:www\.)?(?:youtube\.com/(?:v/|embed/|watch\?v=)|youtu\.be/)([\w-]+)?#i', $unitext[1], $match)) {
                    $video_id = $match[1];
                    $video_string = '<div class="videoWrapper"><iframe src="http://youtube.com/embed/'.$video_id.'?rel=0"></iframe></div>';
                    $unitext[1] = preg_replace('#(?:http://)?(?:https://)?(?:www\.)?(?:youtube\.com/(?:v/|embed/|watch\?v=)|youtu\.be/)([\w-]+)?#i', $video_string, $unitext[1]);
                    $text = $unitext[1];
                }
    
                $titleID = str_replace(' ', '_', trim($title));
    
                $newString = '<span id="'.$titleID.'">'.$title.'</span><div class="university-info-holder"><div class="university-info"><i class="icon icon-close"></i>'.$text.'</div></div>';
    
    
                $row->text = str_replace($matches[0][$k],$newString,$row->text);
    
    
        }
    
    }
    

    }