Fixing content type ordering when content_type is not defined.
[akelos.git] / vendor / PHPCodeAnalyzer / PHPCodeAnalyzer.php
blob23c278fa7a9a740bcbf0f2fe8524e208efcd23e9
1 <?php
2 /**
3 * A class for performing code analysis for php scripts
4 * It is designed to be the heart of a code limiting script
5 * to use with Savant {@link http://phpsavant.com}
7 * This code should be php4 compatiable but i've only run it in php5 and some of the Tokenizer constants have changed
9 * @author Joshua Eichorn <josh@bluga.net>
10 * @copyright Joshua Eichorn 2004
11 * @package PHPCodeAnalyzer
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU Lesser General Public License as
15 * published by the Free Software Foundation; either version 2.1 of the
16 * License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * Lesser General Public License for more details.
23 * @license http://www.gnu.org/copyleft/lesser.html LGPL
26 /**#@+
27 * compat tokeniezer defines
29 if (! defined('T_OLD_FUNCTION')) {
30 define('T_OLD_FUNCTION', T_FUNCTION);
32 if (!defined('T_ML_COMMENT')) {
33 define('T_ML_COMMENT', T_COMMENT);
34 } else {
35 define('T_DOC_COMMENT', T_ML_COMMENT);
37 /**#@-*/
39 /**
40 * Code Analysis class
42 * Example Usage:
43 * <code>
44 * $analyzer = new PHPCodeAnalyzer();
45 * $analyzer->source = file_get_contents(__FILE__);
46 * $analyzer->analyze();
47 * print_r($analyzer->calledMethods);
48 * </code>
50 * @todo is it important to grab the details from creating new functions defines classes?
51 * @todo support php5 only stuff like interface
53 * @version 0.4
54 * @license http://www.gnu.org/copyleft/lesser.html LGPL
55 * @copyright Joshua Eichorn 2004
56 * @package PHPCodeAnalyzer
57 * @author Joshua Eichorn <josh@bluga.net>
59 class PHPCodeAnalyzer
61 /**
62 * Source code to analyze
64 var $source = "";
66 /**
67 * functions called
69 var $calledFunctions = array();
71 /**
72 * Called constructs
74 var $calledConstructs = array();
76 /**
77 * methods called
79 var $calledMethods = array();
81 /**
82 * static methods called
84 var $calledStaticMethods = array();
86 /**
87 * new classes instantiated
89 var $classesInstantiated = array();
91 /**
92 * variables used
94 var $usedVariables = array();
96 /**
97 * member variables used
99 var $usedMemberVariables = array();
102 * classes created
104 var $createdClasses = array();
107 * functions created
109 var $createdFunctions = array();
112 * Files includes or requried
114 var $filesIncluded = array();
116 // private variables
117 /**#@+
118 * @access private
120 var $currentString = null;
121 var $currentStrings = null;
122 var $currentVar = false;
123 var $staticClass = false;
124 var $inNew = false;
125 var $inInclude = false;
126 var $lineNumber = 1;
127 var $_previousToken = null;
128 /**#@-*/
131 * parse source filling informational arrays
133 function analyze()
135 $tokens = token_get_all($this->source);
137 // mapping of token to method to call
138 $handleMap = array(
139 T_STRING => 'handleString',
140 T_CONSTANT_ENCAPSED_STRING => 'handleString',
141 T_ENCAPSED_AND_WHITESPACE => 'handleString',
142 T_CHARACTER => 'handleString',
143 T_NUM_STRING => 'handleString',
144 T_DNUMBER => 'handleString',
145 T_FUNC_C => 'handleString',
146 T_CLASS_C => 'handleString',
147 T_FILE => 'handleString',
148 T_LINE => 'handleString',
149 T_DOUBLE_ARROW => 'handleString',
151 T_ARRAY => 'handleClearStrings',
152 T_CONCAT_EQUAL => 'handleClearStrings',
154 T_DOUBLE_COLON => 'handleDoubleColon',
155 T_NEW => 'handleNew',
156 T_OBJECT_OPERATOR => 'handleObjectOperator',
157 T_VARIABLE => 'handleVariable',
158 T_FUNCTION => 'handleFunction',
159 T_OLD_FUNCTION => 'handleFunction',
160 T_CLASS => 'handleClass',
161 T_WHITESPACE => 'handleWhitespace',
162 T_INLINE_HTML => 'handleWhitespace',
163 T_OPEN_TAG => 'handleWhitespace',
164 T_CLOSE_TAG => 'handleWhitespace',
166 T_AS => 'handleAs',
168 T_ECHO => 'handleConstruct',
169 T_EVAL => 'handleConstruct',
170 T_UNSET => 'handleConstruct',
171 T_ISSET => 'handleConstruct',
172 T_PRINT => 'handleConstruct',
173 T_FOR => 'handleConstruct',
174 T_FOREACH=> 'handleConstruct',
175 T_EMPTY => 'handleConstruct',
176 T_EXIT => 'handleConstruct',
177 T_CASE => 'handleConstruct',
178 T_GLOBAL=> 'handleConstruct',
179 T_UNSET => 'handleConstruct',
180 T_WHILE => 'handleConstruct',
181 T_DO => 'handleConstruct',
182 T_IF => 'handleConstruct',
183 T_LIST => 'handleConstruct',
184 T_RETURN=> 'handleConstruct',
185 T_STATIC=> 'handleConstruct',
186 T_ENDFOR=> 'handleConstruct',
187 T_ENDFOREACH=> 'handleConstruct',
188 T_ENDIF=> 'handleConstruct',
189 T_ENDSWITCH=> 'handleConstruct',
190 T_ENDWHILE=> 'handleConstruct',
192 T_INCLUDE => 'handleInclude',
193 T_INCLUDE_ONCE => 'handleInclude',
194 T_REQUIRE => 'handleInclude',
195 T_REQUIRE_ONCE => 'handleInclude',
198 foreach($tokens as $token)
200 if (is_string($token))
202 // we have a simple 1-character token
203 $this->handleSimpleToken($token);
205 else
207 list($id, $text) = $token;
208 if (isset($handleMap[$id]))
210 $call = $handleMap[$id];
211 $this->$call($id,$text);
213 /*else * /
215 echo token_name($id).": $text<br>\n";
216 } /* */
222 * Handle a 1 char token
223 * @access private
225 function handleSimpleToken($token)
227 if ($token !== ";")
229 $this->currentStrings .= $token;
231 switch($token)
233 case "(":
234 // method is called
235 if ($this->staticClass !== false)
237 if (!isset($this->calledStaticMethods[$this->staticClass][$this->currentString]))
239 $this->calledStaticMethods[$this->staticClass][$this->currentString]
240 = array();
242 $this->calledStaticMethods[$this->staticClass][$this->currentString][]
243 = $this->lineNumber;
244 $this->staticClass = false;
246 else if ($this->currentVar !== false)
248 if (!isset($this->calledMethods[$this->currentVar][$this->currentString]))
250 $this->calledMethods[$this->currentVar][$this->currentString] = array();
252 $this->calledMethods[$this->currentVar][$this->currentString][] = $this->lineNumber;
253 $this->currentVar = false;
255 else if ($this->inNew !== false)
257 $this->classInstantiated();
259 else if ($this->currentString !== null)
261 $this->functionCalled();
263 //$this->currentString = null;
264 break;
265 case "=":
266 case ";":
267 case "?":
268 case ":":
269 if ($this->inNew !== false)
271 $this->classInstantiated();
273 else if ($this->inInclude !== false)
275 $this->fileIncluded();
277 else if ($this->currentVar !== false)
279 $this->useMemberVar();
281 $this->currentString = null;
282 $this->currentStrings = null;
283 break;
285 case ']':
286 $this->useMemberVar(false);
287 break;
288 case '{':
289 if($this->_previousToken == ')'){
290 $this->currentVar = false;
291 $this->currentString = null;
293 break;
295 $this->_previousToken = $token;
299 * handle includes and requires
300 * @access private
302 function handleInclude($id,$text)
304 $this->inInclude = true;
305 $this->handleConstruct($id,$text);
309 * handle String tokens
310 * @access private
312 function handleString($id,$text)
314 $this->currentString = $text;
315 $this->currentStrings .= $text;
319 * handle String tokens
320 * @access private
322 function handleClearStrings($id,$text)
324 $this->currentString = '';
328 * handle variables
329 * @access private
331 function handleVariable($id,$text)
333 $this->currentString = $text;
334 $this->currentStrings .= $text;
335 $this->useVariable();
340 * handle Double Colon tokens
341 * @access private
343 function handleDoubleColon($id,$text)
345 $this->staticClass = $this->currentString;
346 $this->currentString = null;
350 * handle new keyword
351 * @access private
353 function handleNew($id,$text)
355 $this->inNew = true;
359 * handle function
360 * @access private
362 function handleFunction($id,$text)
364 $this->createdFunctions[] = $this->lineNumber;
368 * handle class
369 * @access private
371 function handleClass($id,$text)
373 $this->createdClasses[] = $this->lineNumber;
377 * Handle ->
378 * @access private
380 function handleObjectOperator($id,$text)
382 $this->currentVar = $this->currentString;
383 $this->currentString = null;
384 $this->currentStrings .= $text;
388 * handle whitespace to figure out line counts
389 * @access private
391 function handleWhitespace($id,$text)
393 $this->lineNumber+=substr_count($text,"\n");
394 if ($id == T_CLOSE_TAG)
396 $this->handleSimpleToken(";");
402 * as has been used we must have a var before it
404 * @access private
406 function handleAs($id,$text)
408 $this->handleSimpleToken(";");
412 * a language construct has been called record it
413 * @access private
415 function handleConstruct($id,$construct)
417 if (!isset($this->calledConstructs[$construct]))
419 $this->calledConstructs[$construct] = array();
421 $this->calledConstructs[$construct][] = $this->lineNumber;
422 $this->currentString = null;
426 * a class was Instantiated record it
427 * @access private
429 function classInstantiated()
431 if (!isset($this->classesInstantiated[$this->currentString]))
433 $this->classesInstantiated[$this->currentString] = array();
435 $this->classesInstantiated[$this->currentString][] = $this->lineNumber;
436 $this->inNew = false;
440 * a file was included record it
441 * @access private
443 function fileIncluded()
445 if (!isset($this->filesIncluded[$this->currentStrings]))
447 $this->filesIncluded[$this->currentStrings] = array();
449 $this->filesIncluded[$this->currentStrings][] = $this->lineNumber;
450 $this->inInclude = false;
451 $this->currentString = null;
452 $this->currentStrings = "";
456 * a function was called record it
457 * @access private
459 function functionCalled($id = false)
461 $function_name = trim(rtrim($this->currentStrings,'('));
462 if(empty($this->currentStrings) || substr($function_name,-1) != ']'){
463 $function_name = $this->currentString;
464 if(strstr('"\'',substr($function_name,-1))){
465 $this->currentString = null;
466 return ;
470 if (!isset($this->calledFunctions[$function_name]))
472 $this->calledFunctions[$function_name] = array();
475 $this->calledFunctions[$function_name][] = $this->lineNumber;
476 $this->currentString = null;
480 * we used a member variable record it
481 * @access private
483 function useMemberVar($reset = true)
485 if (!isset($this->usedMemberVariables[$this->currentVar][$this->currentString])){
486 $this->usedMemberVariables[$this->currentVar][$this->currentString] = array();
488 $this->usedMemberVariables[$this->currentVar][$this->currentString][] = $this->lineNumber;
489 if($reset){
490 $this->currentVar = false;
491 $this->currentString = null;
496 * we used a variable record it
497 * @access private
499 function useVariable()
501 if (!isset($this->usedVariables[$this->currentString]))
503 $this->usedVariables[$this->currentString] = array();
505 $this->usedVariables[$this->currentString][] = $this->lineNumber;