@@ -18,22 +18,22 @@ class Compressor
18
18
const COMPRESS_TYPE_LOCAL_VARIABLES = 'local_variables ' ;
19
19
const COMPRESS_TYPE_OBJECT_VARIABLES = 'object_variables ' ;
20
20
const COMPRESS_TYPE_OBJECT_METHODS = 'object_methods ' ;
21
-
21
+
22
22
protected $ content = '' ;
23
23
24
- protected $ whitespaces = false ;
24
+ protected $ strip_whitespaces = false ;
25
25
26
26
protected $ comments = false ;
27
27
28
28
protected $ compress_types = [
29
- 'local_variables ' => false ,
30
- 'object_variables ' => false ,
31
- 'object_methods ' => false ,
29
+ 'local_variables ' => false ,
30
+ 'object_variables ' => false ,
31
+ 'object_methods ' => false ,
32
32
];
33
33
34
34
protected $ exclude_names = [
35
- 'local_variables ' => [
36
- 'this ' => 'this ' ,/** use in Object method scope **/
35
+ 'local_variables ' => [
36
+ 'this ' => 'this ' , /** use in Object method scope **/
37
37
'GLOBALS ' => 'GLOBALS ' ,
38
38
'_GET ' => '_GET ' ,
39
39
'_POST ' => '_POST ' ,
@@ -44,11 +44,11 @@ class Compressor
44
44
'http_response_header ' => 'http_response_header ' ,
45
45
'php_errormsg ' => 'php_errormsg ' ,
46
46
],
47
- 'object_variables ' => [
48
- 'this ' => 'this ' ,
47
+ 'object_variables ' => [
48
+ 'this ' => 'this ' ,
49
49
],
50
-
51
- 'object_methods ' => [
50
+
51
+ 'object_methods ' => [
52
52
//Magic
53
53
'this ' => 'this ' ,
54
54
'__construct ' => '__construct ' ,
@@ -69,7 +69,7 @@ class Compressor
69
69
// only php 7
70
70
'do ' => 'do ' ,
71
71
'as ' => 'as ' ,
72
- ]
72
+ ],
73
73
];
74
74
/**
75
75
* @var NodeTraverser
@@ -82,34 +82,168 @@ public function __construct($data = [])
82
82
}
83
83
84
84
public function compress ()
85
- {
85
+ {
86
86
try {
87
87
$ statements = $ this ->getStatements ();
88
88
$ traverser = $ this ->getTraverser ();
89
89
$ traverser ->addVisitor (new GlobalVisitor ($ this ->getCompressSettings ()));
90
90
$ new_statements = $ traverser ->traverse ($ statements );
91
91
$ this ->content = $ this ->getCompiller ()->prettyPrint ($ new_statements );
92
+ if ($ this ->strip_whitespaces ) {
93
+ $ this ->content = $ this ->stripWhitespaces ($ this ->content );
94
+ }
92
95
} catch (Error $ e ) {
93
96
echo 'Parse Error: ' , $ e ->getMessage ();
94
97
}
95
98
}
99
+
100
+ protected function stripWhitespaces ($ code )
101
+ {
102
+ static $ IW = array (
103
+ T_CONCAT_EQUAL , // .=
104
+ T_DOUBLE_ARROW , // =>
105
+ T_BOOLEAN_AND , // &&
106
+ T_BOOLEAN_OR , // ||
107
+ T_IS_EQUAL , // ==
108
+ T_IS_NOT_EQUAL , // != or <>
109
+ T_IS_SMALLER_OR_EQUAL , // <=
110
+ T_IS_GREATER_OR_EQUAL , // >=
111
+ T_INC , // ++
112
+ T_DEC , // --
113
+ T_PLUS_EQUAL , // +=
114
+ T_MINUS_EQUAL , // -=
115
+ T_MUL_EQUAL , // *=
116
+ T_DIV_EQUAL , // /=
117
+ T_IS_IDENTICAL , // ===
118
+ T_IS_NOT_IDENTICAL , // !==
119
+ T_DOUBLE_COLON , // ::
120
+ T_PAAMAYIM_NEKUDOTAYIM , // ::
121
+ T_OBJECT_OPERATOR , // ->
122
+ T_DOLLAR_OPEN_CURLY_BRACES , // ${
123
+ T_AND_EQUAL , // &=
124
+ T_MOD_EQUAL , // %=
125
+ T_XOR_EQUAL , // ^=
126
+ T_OR_EQUAL , // |=
127
+ T_SL , // <<
128
+ T_SR , // >>
129
+ T_SL_EQUAL , // <<=
130
+ T_SR_EQUAL , // >>=
131
+ );
132
+ $ code = preg_replace ('/\s+/is ' , " " , $ code );
133
+ $ tokens = token_get_all ($ code );
134
+
135
+ $ new = "" ;
136
+ $ c = sizeof ($ tokens );
137
+ $ iw = false ; // ignore whitespace
138
+ $ ih = false ; // in HEREDOC
139
+ $ ls = "" ; // last sign
140
+ $ ot = null ; // open tag
141
+ for ($ i = 0 ; $ i < $ c ; $ i ++) {
142
+ $ token = $ tokens [$ i ];
143
+ if (is_array ($ token )) {
144
+ list ($ tn , $ ts ) = $ token ; // tokens: number, string, line
145
+ $ tname = token_name ($ tn );
146
+ if ($ tn == T_INLINE_HTML ) {
147
+ $ new .= $ ts ;
148
+ $ iw = false ;
149
+ } else {
150
+ if ($ tn == T_OPEN_TAG ) {
151
+ if (strpos ($ ts , " " ) || strpos ($ ts , "\n" ) || strpos ($ ts , "\t" ) || strpos ($ ts , "\r" )) {
152
+ $ ts = rtrim ($ ts );
153
+ }
154
+ $ ts .= " " ;
155
+ $ new .= $ ts ;
156
+ $ ot = T_OPEN_TAG ;
157
+ $ iw = true ;
158
+ } elseif ($ tn == T_OPEN_TAG_WITH_ECHO ) {
159
+ $ new .= $ ts ;
160
+ $ ot = T_OPEN_TAG_WITH_ECHO ;
161
+ $ iw = true ;
162
+ } elseif ($ tn == T_CLOSE_TAG ) {
163
+ if ($ ot == T_OPEN_TAG_WITH_ECHO ) {
164
+ $ new = rtrim ($ new , "; " );
165
+ } else {
166
+ $ ts = " " . $ ts ;
167
+ }
168
+ $ new .= $ ts ;
169
+ $ ot = null ;
170
+ $ iw = false ;
171
+ } elseif (in_array ($ tn , $ IW )) {
172
+ $ new .= $ ts ;
173
+ $ iw = true ;
174
+ } elseif ($ tn == T_CONSTANT_ENCAPSED_STRING
175
+ || $ tn == T_ENCAPSED_AND_WHITESPACE
176
+ ) {
177
+ if ($ ts [0 ] == '" ' ) {
178
+ $ ts = addcslashes ($ ts , "\n\t\r" );
179
+ }
180
+ $ new .= $ ts ;
181
+ $ iw = true ;
182
+ } elseif ($ tn == T_WHITESPACE ) {
183
+ $ nt = @$ tokens [$ i + 1 ];
184
+ if (!$ iw && (!is_string ($ nt ) || $ nt == '$ ' ) && !in_array ($ nt [0 ], $ IW )) {
185
+ $ new .= " " ;
186
+ }
187
+ $ iw = false ;
188
+ } elseif ($ tn == T_START_HEREDOC ) {
189
+ $ new .= "<<<S \n" ;
190
+ $ iw = false ;
191
+ $ ih = true ; // in HEREDOC
192
+ } elseif ($ tn == T_END_HEREDOC ) {
193
+ $ new .= "S; " ;
194
+ $ iw = true ;
195
+ $ ih = false ; // in HEREDOC
196
+ for ($ j = $ i + 1 ; $ j < $ c ; $ j ++) {
197
+ if (is_string ($ tokens [$ j ]) && $ tokens [$ j ] == "; " ) {
198
+ $ i = $ j ;
199
+ break ;
200
+ } else if ($ tokens [$ j ][0 ] == T_CLOSE_TAG ) {
201
+ break ;
202
+ }
203
+ }
204
+ } elseif ($ tn == T_COMMENT || $ tn == T_DOC_COMMENT ) {
205
+ $ iw = true ;
206
+ } else {
207
+ if (!$ ih ) {
208
+ //$ts = strtolower($ts);
209
+ }
210
+ $ new .= $ ts ;
211
+ $ iw = false ;
212
+ }
213
+ }
214
+ $ ls = "" ;
215
+ } else {
216
+ if (($ token != "; " && $ token != ": " ) || $ ls != $ token ) {
217
+ $ new .= $ token ;
218
+ $ ls = $ token ;
219
+ }
220
+ $ iw = true ;
221
+ }
222
+ }
223
+
224
+ return $ new ;
225
+ }
96
226
97
- public function setExcludeNames ($ type = '' , array $ exclude_names ) {
98
- if (isset ($ this ->compress_types [$ type ])) {
227
+ public function setExcludeNames ($ type = '' , array $ exclude_names )
228
+ {
229
+ if (isset ($ this ->compress_types [$ type ])) {
99
230
$ this ->exclude_names [$ type ] += $ exclude_names ;
100
231
}
101
232
}
233
+
102
234
protected function getCompressSettings ()
103
235
{
104
236
$ settings = [];
105
237
foreach ($ this ->compress_types as $ type => $ enable ) {
106
238
$ settings [$ type ] = [
107
- 'enable ' => $ enable ,
108
- 'exclude_names ' => $ this ->exclude_names [$ type ]
239
+ 'enable ' => $ enable ,
240
+ 'exclude_names ' => $ this ->exclude_names [$ type ],
109
241
];
110
242
}
243
+
111
244
return $ settings ;
112
245
}
246
+
113
247
public function getContent ()
114
248
{
115
249
return $ this ->content ;
@@ -164,11 +298,16 @@ public function compressObjectsMethodsName()
164
298
$ this ->compress_types ['object_methods ' ] = true ;
165
299
}
166
300
301
+ public function compresWhitespaces ()
302
+ {
303
+ $ this ->strip_whitespaces = true ;
304
+ }
305
+
167
306
168
307
public function setContentByFile ($ file )
169
308
{
170
309
if (false === file_exists ($ file )) {
171
- throw new \Exception ('Not found file ' . $ file );
310
+ throw new \Exception ('Not found file ' . $ file );
172
311
}
173
312
return $ this ->content = file_get_contents ($ file );
174
313
}
0 commit comments