1
1
<?php
2
2
3
- namespace PhpTemplates \ Dom ;
3
+ namespace PhpDom ;
4
4
5
5
use Closure ;
6
- use PhpTemplates \ InvalidNodeException ;
7
- use PhpTemplates \ Source ;
6
+ use SplFileInfo ;
7
+
8
8
// todo: validari cu tipete
9
9
class Parser
10
10
{
11
- private $ dom ;
12
- private $ nodeQueue = [];
11
+ public static $ repair_html = false ;
12
+ public static $ throw_errors = false ;
13
+
14
+ private ?DomNode $ dom ;
15
+ private array $ nodeQueue = [];
13
16
14
- private $ line = 1 ;
15
- private $ scope = 'text ' ;
16
- private $ buildingNode ;
17
- private $ buildingAttr ;
17
+ private ?SplFileInfo $ file ;
18
+ private int $ line = 1 ;
19
+ private string $ scope = 'text ' ;
20
+ private ?DomElementInterface $ buildingNode ;
21
+ private ?DomNodeAttrInterface $ buildingAttr ;
18
22
19
- private $ options = [
20
- 'repair_html ' => false ,
21
- 'throw_errors ' => false ,
22
- ];
23
+ private $ options = [];
23
24
24
25
public function __construct (array $ options = [])
25
26
{
26
- $ this ->options = array_merge ($ this ->options , $ options );
27
+ $ this ->options = array_merge ([
28
+ 'repair_html ' => self ::$ repair_html ,
29
+ 'throw_errors ' => self ::$ throw_errors ,
30
+ ], $ options );
27
31
}
28
32
29
- public function parse (/*Source*/ $ source )
30
- {todo source class
31
- $ this ->dom = new DomNode ('#root ' );
33
+ public function parse (Source $ source )
34
+ {
35
+ // reset
36
+ $ this ->file = new SplFileInfo ($ source ->getFile ());
37
+ $ this ->line = 1 ;
38
+ $ this ->dom = new DomNode ('' );
32
39
$ this ->nodeQueue = [];
40
+ $ this ->scope = 'text ' ;
41
+ $ this ->buildingNode = null ;
42
+ $ this ->buildingAttr = null ;
33
43
34
- $ html = (string )$ source ;
35
- $ chars = array_map ('preg_quote ' , [
36
- '< ' ,
37
- '> ' ,
38
- '= ' ,
39
- '" ' ,
40
- '\'' ,
41
- //'!',
42
- //'?',
43
- //'-',
44
- //'\\',
45
- ]);
46
- $ chars = implode ('| ' , array_merge ([
47
- '<[a-zA-Z0-9_\-]+ ' ,
48
- '<\/[a-zA-Z0-9_\-]+> ' ,
49
- '\/> ' ,
50
- '<!-- ' ,
51
- '--> ' ,
52
- '= *" ' ,
53
- '= * \'' ,
54
- '[\s\t ]+ ' ,
55
- '[\n\r] ' ,
56
- ], $ chars ));
57
-
58
- $ tokens = preg_split ("/( $ chars)/ms " , $ html , -1 , PREG_SPLIT_DELIM_CAPTURE );
44
+ // parse
45
+ $ tokens = $ this ->tokenize ((string )$ source );
59
46
foreach ($ tokens as $ token ) {
60
47
$ this ->add ($ token );
61
48
}
62
49
50
+ // return nodelist or node (if only one root element found)
63
51
if ($ this ->dom ->getChildNodes ()->count () > 1 ) {
64
52
return $ this ->dom ->getChildNodes ();
65
53
}
66
54
67
55
return $ this ->dom ->getChildNodes ()->first ();
68
56
}
57
+
58
+ // split html string into relevant tokens to be interpreted in context
59
+ protected function tokenize (string $ html )
60
+ {
61
+ static $ chars ;
62
+ if (!$ chars )
63
+ {
64
+ $ chars = array_map ('preg_quote ' , [
65
+ '< ' ,
66
+ '> ' ,
67
+ '= ' ,
68
+ '" ' ,
69
+ '\'' ,
70
+ //'!',
71
+ //'?',
72
+ //'-',
73
+ //'\\',
74
+ ]);
75
+ $ chars = implode ('| ' , array_merge ([
76
+ '<[a-zA-Z0-9_\-]+ ' ,
77
+ '<\/[a-zA-Z0-9_\-]+> ' ,
78
+ '\/> ' ,
79
+ '<!-- ' ,
80
+ '--> ' ,
81
+ '= *" ' ,
82
+ '= * \'' ,
83
+ '[\s\t ]+ ' ,
84
+ '[\n\r] ' ,
85
+ ], $ chars ));
86
+ }
87
+
88
+ return preg_split ("/( $ chars)/ms " , $ html , -1 , PREG_SPLIT_DELIM_CAPTURE );
89
+ }
69
90
70
91
protected function add ($ token )
71
92
{
@@ -100,7 +121,8 @@ protected function textScope($token)
100
121
// treat it as text
101
122
return $ this ->buildingNode ->append ($ token );
102
123
}
103
- throw new \Exception ("Unexpected token $ token at line {$ this ->line }, expecting end tag for node < {$ parentNode ->getNodeName ()}> started at line {$ parentNode ->meta ['lineNumber ' ]}" );
124
+ $ inFile = $ this ->file ? 'in ' . $ this ->file ->getRealPath () : '' ;
125
+ throw new \Exception ("Unexpected token $ token $ inFile at line {$ this ->line }, expecting end tag for node < {$ parentNode ->getNodeName ()}> started at line {$ parentNode ->meta ['line ' ]}" );
104
126
}
105
127
106
128
if (trim ($ this ->buildingNode ->getNodeValue ()) !== '' ) {
@@ -119,7 +141,8 @@ protected function textScope($token)
119
141
}
120
142
121
143
$ this ->buildingNode = new DomNode ($ m [1 ]);
122
- $ this ->buildingNode ->meta ['lineNumber ' ] = $ this ->line ;
144
+ $ this ->buildingNode ->meta ['file ' ] = $ this ->file ;
145
+ $ this ->buildingNode ->meta ['line ' ] = $ this ->line ;
123
146
$ this ->scope = 'nodeDeclaration ' ;
124
147
}
125
148
@@ -239,7 +262,10 @@ protected function tryCloseTag($name)
239
262
$ parentNode = $ parentNode ? $ parentNode : $ this ->dom ;
240
263
241
264
if ($ name == 'br ' ) {
242
- return $ parentNode ->appendChild (new DomNode ('br ' ));
265
+ $ br = new DomNode ('br ' );
266
+ $ br ->meta ['file ' ] = $ this ->file ;
267
+ $ br ->meta ['line ' ] = $ this ->line ;
268
+ return $ parentNode ->appendChild ($ br );
243
269
}
244
270
245
271
$ max = count ($ this ->nodeQueue ) -1 ;
0 commit comments