简体   繁体   English

如何重构 function 以在多个 arrays 中将 preg_replace_callback() 与多个正则表达式字符串和替换字符串一起使用?

[英]How to refactor a function to use preg_replace_callback() with multiple regex strings and replacement strings in multiple arrays?

I am refactoring some legacy PHP code (version 5.5) and I need to refactor a function to use preg_replace_callback() from preg_replace() (this is because of a \e evaluation deprecation) however what is being passed into the only 2 preg_replace() calls are arrays of search patterns and arrays of replacements.我正在重构一些旧版 PHP 代码(版本 5.5),我需要重构 function 以使用 preg_replace() 中的 preg_replace_callback() (这是因为不推荐使用 \e 评估 2 pregre)但是仅传递到调用是搜索模式的 arrays 和替换的 arrays。

I am aware I need to pass in a callback function to preg_replace_callback() but what would be the way to go about this when each pattern is different?我知道我需要将回调 function 传递给 preg_replace_callback() 但是当每种模式不同时,go 的方法是什么?

    function format($in, $options = 0)
{
    if (!$options) {
        $options = FORMAT_BREAKS | FORMAT_HTMLCHARS | FORMAT_CENSOR;
    }

    if ($options & FORMAT_CENSOR) {
        if (!$this->replaces_loaded) {
            $this->get_replaces();
        }

        if ($this->censor) {
            $in = preg_replace($this->censor, '####', $in);
        }
    }

    if ($options & FORMAT_MBCODE) {
        $search = array(
            '~(^|\s)([a-z0-9-_.]+@[a-z0-9-.]+\.[a-z0-9-_.]+)~i',
            '~(^|\s)(http|https|ftp)://(\w+[^\s\[\]]+)~ise'
        );

        $replace = array(
            '\\1[email]\\2[/email]',
            '\'\\1[url]\' .wordwrap(\'\\2://\\3\', 1, \' \', 1) . \'[/url]\''
        );

        $brackets = (strpos($in, '[') !== false) && (strpos($in, ']') !== false);

        if ($brackets) {
            $b_search = array(
                '~\[code](.*?)\[/code]~ise',
                '~\[php](.*?)\[/php]~ise',
                '~\[php=([0-9]+?)](.*?)\[/php]~ise',
                '~\[img](http|https|ftp)://(.*?)\[/img]~ise',
                '~\[url](.*?)\[/url]~ise',
                '~\[url=(http|https|ftp)://(.+?)](.+?)\[/url]~ise'
            );

            $b_replace = array(
                '\'[code]\' . function (array $matches){ return base64_encode(\'\\1\') . \'[/code]\'',
                '\'[php]\' . base64_encode(\'\\1\') . \'[/php]\'',
                '\'[php=\\1]\' . base64_encode(\'\\2\') . \'[/php]\'',
                '\'[img]\' . wordwrap(\'\\1://\\2\', 1, \' \', 1) . \'[/img]\'',
                '\'[url]\' . wordwrap(\'\\1\\2\', 1, \' \', 1) . \'[/url]\'',
                '\'[url=\' . wordwrap(\'\\1://\\2\', 1, \' \', 1) . \']\\3[/url]\''
            );

            $search  = array_merge($search, $b_search);
            $replace = array_merge($replace, $b_replace);

            error_log(print_r($replace));
        }
        
        $in = preg_replace($search, $replace, $in);

        $brackets = (strpos($in, '[') !== false) && (strpos($in, ']') !== false); //We may have auto-parsed a URL, adding a bracket
    }

    $strtr = array();

    if ($options & FORMAT_HTMLCHARS) {
        $strtr['&'] = '&';
        $strtr['"'] = '"';
        $strtr['\''] = ''';
        $strtr['<'] = '&lt;';
        $strtr['>'] = '&gt;';
    }

    if ($options & FORMAT_BREAKS) {
        $strtr["\n"] = "<br />\n";
    }

    if ($this->user['user_view_emoticons'] && ($options & FORMAT_EMOTICONS)) {
        if (!$this->replaces_loaded) {
            $this->get_replaces();
        }

        $strtr = array_merge($strtr, $this->emotes['replacement']);
    }

    $in = strtr($in, $strtr);

    if (($options & FORMAT_MBCODE) && $brackets) {
        $search = array(
            '~\[(/)?([bi])]~i',
            '~\[u]~i',
            '~\[s]~i',
            '~\[/[us]]~i',
            '~\[url](h t t p|h t t p s|f t p) : / /(.+?)\[/url]~ise',
            '~\[url=(h t t p|h t t p s|f t p) : / /(.+?)](.+?)\[/url]~ise',
            '~\[email]([a-z0-9-_.]+@[a-z0-9-.]+\.[a-z0-9-_.]+)?\[/email]~i',
            '~\[email=([^<]+?)](.*?)\[/email]~i',
            '~\[img](h t t p|h t t p s|f t p) : / /(.*?)\[/img]~ise',
            '~\[(right|center)](.*?)\[/\1]~is',
            '~\[code](.*?)\[/code]~ise',
            '~\[php](.*?)\[/php]~ise',
            '~\[php=([0-9]+?)](.*?)\[/php]~ise',
            '~\[color=(\S+?)](.*?)\[/color]~is',
            '~\[font=(.+?)](.*?)\[/font]~is',
            '~\[size=([0-9]+?)](.*?)\[/size]~is'
        );

        $replace = array(
            '<\\1\\2>',
            '<span style=\'text-decoration:underline\'>',
            '<span style=\'text-decoration:line-through\'>',
            '</span>',
            '\'<a href="\' . str_replace(\' \', \'\', \'\\1://\\2\') . \'" onclick="window.open(this.href,\\\'' . $this->sets['link_target'] . '\\\');return false;">\' . str_replace(\' \', \'\', \'\\1://\\2\') . \'</a>\'',
            '\'<a href="\' . str_replace(\' \', \'\', \'\\1://\\2\') . \'" onclick="window.open(this.href,\\\'' . $this->sets['link_target'] . '\\\');return false;">\\3</a>\'',
            '<a href="mailto:\\1">\\1</a>',
            '<a href="mailto:\\1">\\2</a>',
            '\'<img src="\' . str_replace(\' \', \'\', \'\\1://\\2\') . \'" alt="\' . str_replace(\' \', \'\', \'\\1://\\2\') . \'" />\'',
            '<div align="\\1">\\2</div>',
            '$this->format_code(\'\\1\', 0)',
            '$this->format_code(\'\\1\', 1)',
            '$this->format_code(\'\\2\', 1, \'\\1\')',
            '<span style=\'color:\\1\'>\\2</span>',
            '<span style=\'font-family:\\1\'>\\2</span>',
            '<span style=\'font-size:\\1ex\'>\\2</span>'
        );

        if ((substr_count($in, '[quote]') + substr_count($in, '[quote=')) == substr_count($in, '[/quote]')) {
            $search[] = '~\[quote=(.+?)]~i';
            $search[] = '~\[quote]~i';
            $search[] = '~\[/quote]~i';

            $replace[] = '<table style="width:90%; margin-left:5%; margin-right:5%;" border="0" cellpadding="3" cellspacing="0"><tr><td><b>\\1 ' . $this->lang->main_said . ':</b></td></tr><tr><td class="quote">';
            $replace[] = '<table style="width:90%; margin-left:5%; margin-right:5%;" border="0" cellpadding="3" cellspacing="0"><tr><td><b>' . $this->lang->main_quote . ':</b></td></tr><tr><td class="quote">';
            $replace[] = '</td></tr></table>';
        }

        $in = preg_replace_callback($search, $replace, $in);
        $in = str_replace(array('  ', "\t", '&amp;#'), array('&nbsp; ', '&nbsp; &nbsp; ', '&#'), $in);
    }

    return $in;
}

I tested trying to place an anonymous functions directly into the replacement arrays but was served the error: Object of class Closure could not be converted to string.我测试了尝试将匿名函数直接放入替换 arrays 但得到错误:Object of class Closure 无法转换为字符串。 But perhaps I may have gone about it incorrectly?但也许我做错了?

            $replace = array(
            '\\1[email]\\2[/email]',
            "'\'\\1[url]\'" . function (array $matches) {return wordwrap($matches[1], $matches[2], $matches[3], $matches[4]); }  . " \'[/url]\''"
        );

Advice would be much appreciated.建议将不胜感激。

Create an associative array where the keys contain regex patterns and the values contain the callbacks (no prepending/appending strings to the callbacks).创建一个关联数组,其中键包含正则表达式模式,值包含回调(回调中没有前置/附加字符串)。

I am not going to rewrite that behemoth from my phone, so I'll demonstrate a single replacement.我不会用我的手机重写那个庞然大物,所以我将演示一个替换。

Feed your array of patterns and callbacks to preg_replace_callback_array() .将您的模式和回调数组提供给preg_replace_callback_array()

Code: ( Demo )代码:(演示

$patternCallbacks = [
    '~\[code](.*?)\[/code]~is' =>
        function($m) {
            return '[code]' . base64_encode($m[1]) . '[/code]';
        },
    // add more elements as needed...
];

echo preg_replace_callback_array(
         $patternCallbacks,
         'This is my [code]script[/code] to display'
     );

Output: Output:

This is my [code]c2NyaXB0[/code] to display

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM