-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathWTemplateParser.php
157 lines (140 loc) · 4.1 KB
/
WTemplateParser.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
<?php
/**
* WTemplateParser.php
*/
/**
* WTemplateParser is the parser part of WTemplate.
*
* @package WTemplate
* @author Johan Dufau <[email protected]>
* @version 1.0.0-04-06-2018
*/
class WTemplateParser {
/**
* Replaces all nodes found in $string by the callback result.
*
* If the char '{' is backslashed or directly followed by a carriage return, it will be ignored.
*
* @param string $string A string to parse.
* @param string $callback The callback to call to replace the node.
* @return string The parsed string on which all callback's results are in it.
* @throws Exception
*/
public static function replaceNodes($string, $callback) {
$length = strlen($string);
$level = 0;
$code = ""; // $code stocks the entire code compiled
$tmp_array = array(0 => ''); // $tmp_array stocks the node (and sub-nodes) currently being read
$last_char = '';
$comment = false;
if (!is_callable($callback)) {
if (is_array($callback)) {
$class = is_object($callback[0]) ? get_class($callback[0]) : $callback[0];
$callback = $class.'::'.$callback[1];
}
throw new Exception("WTemplateParser::replaceNodes(): callback function \"".$callback."\" given is not callable.");
}
for ($i = 0; $i < strlen($string); $i++) {
// Get next char
$char = $string[$i];
switch ($char) {
case '\\': // backslash
// backslash in a node are always saved since it is up to self::findAllNodes to manage them
if ($level > 0) {
$tmp_array[$level] .= '\\';
} else {
if ($last_char == '\\') {
$code .= '\\';
// $char set to null in order to set $last_char to null because the '\' char has been canceled by the previous '\'
$char = '';
}
}
break;
case '%': // comment node
if ($level > 0 && $last_char == '{') {
$comment = true;
} else if ($last_char == '%') {
if ($level > 0) {
$tmp_array[$level] .= '%';
} else {
$code .= '%';
}
}
break;
case '{':
if (!$comment) {
// Check whether { is backslashed
// List of authorized chars to start a node (alphanum, / for closing nodes and $ for var displaying nodes
if ($i < $length-1 && preg_match('#[a-zA-Z0-9/$!%]#', $string[$i+1]) && $last_char != '\\') {
$level++;
// Create a new level in the temporary array
$tmp_array[$level] = '';
} else {
// Are we in a node?
if ($level > 0) {
$tmp_array[$level] .= '{';
} else {
$code .= '{';
}
}
}
break;
case '}':
if ($level > 0) {
if (!$comment) {
// Check whether } is backslashed
if ($last_char != '\\') {
$level--;
// Immediately compile superior level
$tmp_array[$level] .= call_user_func($callback, $tmp_array[$level+1], $level > 0);
// Delete superior level
unset($tmp_array[$level+1]);
} else {
// Add the closing bracket
$tmp_array[$level] .= '}';
}
// We arrived at the end of the node
if ($level == 0) {
// Add the compile node to the global string $code
$code .= $tmp_array[0];
// Clean temporary array
$tmp_array = array(0 => '');
}
} else if ($last_char == '%') {
$comment = false;
$level--;
$tmp_array = array(0 => '');
}
} else {
$code .= '}';
}
break;
default:
if ($char == "\n" && $level > 0 && !$comment) {
throw new Exception("WTemplateParser::replaceNodes(): found illegal carriage return character in a node (".$tmp_array[$level].").");
}
if ($level > 0) {
// We are in a node. Special chars may be used
// so add them back
if ($last_char == '\\') {
$tmp_array[$level] .= '\\';
} else if ($last_char == '%') {
$tmp_array[$level] .= '%';
}
$tmp_array[$level] .= $char;
} else {
if ($last_char == '\\') {
$code .= '\\';
} else if ($last_char == '%') {
$code .= '%';
}
$code .= $char;
}
break;
}
$last_char = $char;
}
return $code;
}
}
?>