像Wordcode一样解析Wordpress

时间:2013-03-31 22:23:07

标签: php

我想用Wordpress解析像Wordpress这样的短代码:

输入:

[include file="header.html"]

我需要输出数组,函数名称“include”和带有值的属性,任何帮助都将受到赞赏。

谢谢

6 个答案:

答案 0 :(得分:4)

使用this function

$code = '[include file="header.html"]';
$innerCode = GetBetween($code, '[', ']');
$innerCodeParts = explode(' ', $innerCode);

$command = $innerCodeParts[0];

$attributeAndValue = $innerCodeParts[1];
$attributeParts = explode('=', $attributeParts);
$attribute = $attributeParts[0];
$attributeValue = str_replace('\"', '', $attributeParts[1]);

echo $command . ' ' . $attribute . '=' . $attributeValue;
//this will result in include file=header.html

$ command将是“include”

$属性将是“文件”

$ attributeValue将是“header.html”

答案 1 :(得分:4)

这是我们在项目中使用的实用工具类 它将匹配字符串中的所有短代码(包括html),它将输出一个关联数组,包括nameattributescontent

final class Parser {

    // Regex101 reference: https://regex101.com/r/pJ7lO1
    const SHORTOCODE_REGEXP = "/(?P<shortcode>(?:(?:\\s?\\[))(?P<name>[\\w\\-]{3,})(?:\\s(?P<attrs>[\\w\\d,\\s=\\\"\\'\\-\\+\\#\\%\\!\\~\\`\\&\\.\\s\\:\\/\\?\\|]+))?(?:\\])(?:(?P<content>[\\w\\d\\,\\!\\@\\#\\$\\%\\^\\&\\*\\(\\\\)\\s\\=\\\"\\'\\-\\+\\&\\.\\s\\:\\/\\?\\|\\<\\>]+)(?:\\[\\/[\\w\\-\\_]+\\]))?)/u";

    // Regex101 reference: https://regex101.com/r/sZ7wP0
    const ATTRIBUTE_REGEXP = "/(?<name>\\S+)=[\"']?(?P<value>(?:.(?![\"']?\\s+(?:\\S+)=|[>\"']))+.)[\"']?/u";

    public static function parse_shortcodes($text) {
        preg_match_all(self::SHORTOCODE_REGEXP, $text, $matches, PREG_SET_ORDER);
        $shortcodes = array();
        foreach ($matches as $i => $value) {
            $shortcodes[$i]['shortcode'] = $value['shortcode'];
            $shortcodes[$i]['name'] = $value['name'];
            if (isset($value['attrs'])) {
                $attrs = self::parse_attrs($value['attrs']);
                $shortcodes[$i]['attrs'] = $attrs;
            }
            if (isset($value['content'])) {
                $shortcodes[$i]['content'] = $value['content'];
            }
        }

        return $shortcodes;
    }

    private static function parse_attrs($attrs) {
        preg_match_all(self::ATTRIBUTE_REGEXP, $attrs, $matches, PREG_SET_ORDER);
        $attributes = array();
        foreach ($matches as $i => $value) {
            $key = $value['name'];
            $attributes[$i][$key] = $value['value'];
        }
        return $attributes;
    }
}

print_r(Parser::parse_shortcodes('[include file="header.html"]'));

输出:

Array
(
    [0] => Array
        (
            [shortcode] => [include file="header.html"]
            [name] => include
            [attrs] => Array
                (
                    [0] => Array
                        (
                            [file] => header.html
                        )
                )
        )
)

答案 2 :(得分:3)

我在PHP框架中也需要这个功能。这就是我写的,它运作得很好。它适用于匿名函数,我非常喜欢它(它有点像JavaScript中的回调函数)。

<?php
//The content which should be parsed
$content = '<p>Hello, my name is John an my age is [calc-age day="4" month="10" year="1991"].</p>';
$content .= '<p>Hello, my name is Carol an my age is [calc-age day="26" month="11" year="1996"].</p>';

//The array with all the shortcode handlers. This is just a regular associative array with anonymous functions as values. A very cool new feature in PHP, just like callbacks in JavaScript or delegates in C#.
$shortcodes = array(
    "calc-age" => function($data){
        $content = "";
        //Calculate the age
        if(isset($data["day"], $data["month"], $data["year"])){
            $age = date("Y") - $data["year"];
            if(date("m") < $data["month"]){
                $age--;
            }
            if(date("m") == $data["month"] && date("d") < $data["day"]){
                $age--;
            }
            $content = $age;
        }
        return $content;
    }
);
//http://stackoverflow.com/questions/18196159/regex-extract-variables-from-shortcode
function handleShortcodes($content, $shortcodes){
    //Loop through all shortcodes
    foreach($shortcodes as $key => $function){
        $dat = array();
        preg_match_all("/\[".$key." (.+?)\]/", $content, $dat);
        if(count($dat) > 0 && $dat[0] != array() && isset($dat[1])){
            $i = 0;
            $actual_string = $dat[0];
            foreach($dat[1] as $temp){
                $temp = explode(" ", $temp);
                $params = array();
                foreach ($temp as $d){
                    list($opt, $val) = explode("=", $d);
                    $params[$opt] = trim($val, '"');
                }
                $content = str_replace($actual_string[$i], $function($params), $content);
                $i++;
            }
        }
    }
    return $content;
}
echo handleShortcodes($content, $shortcodes);
?>

结果:
你好,我的名字是John,我的年龄是22岁 你好,我的名字是卡罗尔,我的年龄是17岁。

答案 3 :(得分:1)

这实际上比表面上看起来更难。安德鲁的回答是有效的,但如果在源文本中出现方括号[例如],则会开始分解。 WordPress的工作原理是预先注册一个有效的短代码列表,如果匹配其中一个预定义值,则只对括号内的文本起作用。这样,它就不会破坏任何可能碰巧有一组方括号的常规文本。

WordPress短代码引擎的实际source code相当强大,并且看起来修改文件自行运行并不困难 - 那么你可以使用它你的申请处理艰苦的工作。 (如果您有兴趣,请查看该文件中的get_shortcode_regex(),看看这个问题的正确解决方案实际上有多毛茸茸。)

使用WP shortcodes.php粗略地实现您的问题会看起来像 那样:

// Define the shortcode
function inlude_shortcode_func($attrs) {
    $data = shortcode_atts(array(
        'file' => 'default'
    ), $attrs);

    return "Including File: {$data['file']}";
}
add_shortcode('include', 'inlude_shortcode_func');

// And then run your page content through the filter
echo do_shortcode('This is a document with [include file="header.html"] included!');

同样,根本没有经过测试,但它不是一个非常难以使用的API。

答案 4 :(得分:0)

更新@Duco的代码段,好像它爆炸了一样,当我们有类似

[Image source="myimage.jpg" alt="My Image"]

当前版本:

function handleShortcodes($content, $shortcodes){
    function read_attr($attr) {
        $atList = [];

        if (preg_match_all('/\s*(?:([a-z0-9-]+)\s*=\s*"([^"]*)")|(?:\s+([a-z0-9-]+)(?=\s*|>|\s+[a..z0-9]+))/i', $attr, $m)) {
            for ($i = 0; $i < count($m[0]); $i++) {
                if ($m[3][$i])
                    $atList[$m[3][$i]] = null;
                else
                    $atList[$m[1][$i]] = $m[2][$i];
            }
        }
        return $atList;
    }
    //Loop through all shortcodes
    foreach($shortcodes as $key => $function){
        $dat = array();
        preg_match_all("/\[".$key." (.+?)\]/", $content, $dat);

        if(count($dat) > 0 && $dat[0] != array() && isset($dat[1])){
            $i = 0;
            $actual_string = $dat[0];
            foreach($dat[1] as $temp){
                $params = read_attr($temp);
                $content = str_replace($actual_string[$i], $function($params), $content);
                $i++;
            }
        }
    }
    return $content;
}
$content = '[image source="one" alt="one two"]';

结果:

array( 
  [source] => myimage.jpg,
  [alt] => My Image
)

答案 5 :(得分:0)

我用wordpress功能修改了上述功能

function extractThis($short_code_string) {
    $shortocode_regexp = "/(?P<shortcode>(?:(?:\\s?\\[))(?P<name>[\\w\\-]{3,})(?:\\s(?P<attrs>[\\w\\d,\\s=\\\"\\'\\-\\+\\#\\%\\!\\~\\`\\&\\.\\s\\:\\/\\?\\|]+))?(?:\\])(?:(?P<content>[\\w\\d\\,\\!\\@\\#\\$\\%\\^\\&\\*\\(\\\\)\\s\\=\\\"\\'\\-\\+\\&\\.\\s\\:\\/\\?\\|\\<\\>]+)(?:\\[\\/[\\w\\-\\_]+\\]))?)/u";
    preg_match_all($shortocode_regexp, $short_code_string, $matches, PREG_SET_ORDER);
    $shortcodes = array();
    foreach ($matches as $i => $value) {
       $shortcodes[$i]['shortcode'] = $value['shortcode'];
       $shortcodes[$i]['name'] = $value['name'];
       if (isset($value['attrs'])) {
        $attrs = shortcode_parse_atts($value['attrs']);
        $shortcodes[$i]['attrs'] = $attrs;
       }
       if (isset($value['content'])) {
        $shortcodes[$i]['content'] = $value['content'];
       }
    }
    return $shortcodes;
  }

我认为这对所有人都有帮助:)