Passed
Push — master ( e1b8c4...ea4361 )
by 世昌
01:52
created

Compiler   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 138
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 54
dl 0
loc 138
rs 10
c 0
b 0
f 0
wmc 22

8 Methods

Rating   Name   Duplication   Size   Complexity  
A proccesCommands() 0 9 2
A compileText() 0 19 4
A registerTag() 0 3 1
A proccesTags() 0 13 3
A doMatchCommand() 0 18 6
A applyTagConfig() 0 5 3
A registerCommand() 0 3 1
A __construct() 0 5 2
1
<?php
2
namespace suda\component\template;
3
4
use suda\component\template\Tag;
5
use suda\component\template\TemplateLoader;
0 ignored issues
show
Bug introduced by
The type suda\component\template\TemplateLoader was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
6
7
8
/**
9
 * 可执行命令表达式
10
 *
11
 */
12
class Compiler
13
{
14
    /**
15
     * 定义的标签
16
     *
17
     * @var array
18
     */
19
    protected $tag = [
20
        'raw' => ['{{!', '}}', '<?php echo $code; ?>'],
21
        'comment' => ['{--', '--}', '<?php /* $code */ ?>'],
22
    ];
23
24
    /**
25
     * 编译的TAG
26
     *
27
     * @var Tag[]
28
     */
29
    protected $tags=[];
30
31
    /**
32
     * 命令对象
33
     *
34
     * @var CommandInterface[]
35
     */
36
    protected $commands=[];
37
38
    public function __construct()
39
    {
40
        $this->registerCommand(new Command);
41
        foreach ($this->tag as $name => $value) {
42
            $this->registerTag(new Tag($name, $value[0], $value[1], $value[2]));
43
        }
44
    }
45
46
    /**
47
     * 注册命令
48
     *
49
     * @param CommandInterface $command
50
     * @return void
51
     */
52
    public function registerCommand(CommandInterface $command)
53
    {
54
        $this->commands[] = $command;
55
    }
56
57
    /**
58
     * 注册标记
59
     *
60
     * @param Tag $tag
61
     * @return void
62
     */
63
    public function registerTag(Tag $tag)
64
    {
65
        $this->tags[$tag->getName()] =$tag;
66
    }
67
68
    /**
69
     * 编译
70
     *
71
     * @param string $text 代码文本
72
     * @param array $tagConfig 标签配置
73
     * @return string
74
     */
75
    public function compileText(string $text, array $tagConfig = []):string
76
    {
77
        $this->applyTagConfig($tagConfig);
78
        $result  = '';
79
        foreach (token_get_all($text) as $token) {
80
            if (is_array($token)) {
81
                list($tag, $content) = $token;
82
                // 所有将要编译的文本
83
                // 跳过各种的PHP
84
                if ($tag == T_INLINE_HTML) {
85
                    $content=$this->proccesTags($content);
86
                    $content=$this->proccesCommands($content);
87
                }
88
                $result .= $content;
89
            } else {
90
                $result .= $token;
91
            }
92
        }
93
        return $result;
94
    }
95
96
    protected function applyTagConfig(array $config)
97
    {
98
        foreach ($config as $name => $config) {
99
            if (array_key_exists($name, $this->tags)) {
100
                $this->tags[$name]->setConfig($config);
101
            }
102
        }
103
    }
104
105
106
    protected function proccesTags(string $text):string
107
    {
108
        foreach ($this->tags as $tag) {
109
            $pregExp = sprintf('/(!)?%s\s*(.+?)\s*%s/', preg_quote($tag->getOpen()), preg_quote($tag->getClose()));
110
            $text = \preg_replace_callback($pregExp, function ($match) use ($tag) {
111
                if ($match[1] === '!') {
112
                    return substr($match[0], 1);
113
                } else {
114
                    return $tag->compile($match[2]);
115
                }
116
            }, $text);
117
        }
118
        return $text;
119
    }
120
121
    protected function proccesCommands(string $text):string
122
    {
123
        $pregExp ='/\B\@(\!)?([\w\x{4e00}-\x{9aff}]+)(\s*)(\( ( (?>[^()]+) | (?4) )* \) )? /ux';
124
        $code = preg_replace_callback($pregExp, [$this,'doMatchCommand'], $text);
125
        $error = preg_last_error();
126
        if ($error !== PREG_NO_ERROR) {
127
            throw new \Exception($error);
128
        }
129
        return $code;
130
    }
131
132
    protected function doMatchCommand($match)
133
    {
134
        if (count($match) >= 5) {
135
            list($input, $ignore, $name, $space, $params) = $match;
136
        } else {
137
            list($input, $ignore, $name, $space) = $match;
138
            $params = '';
139
        }
140
        if ($ignore ==='!') {
141
            return \str_replace('@!', '@', $input);
142
        } else {
143
            foreach ($this->commands as $command) {
144
                if ($command->has($name)) {
145
                    $code = $command->parse($name, $params);
146
                    return empty($params) ? $code : $code.$space;
147
                }
148
            }
149
            return $input;
150
        }
151
    }
152
}
153