| [ Index ] |
PHP Cross Reference of Akelos Framework |
[Summary view] [Print] [Text view]
1 <?php 2 3 4 class AkReflection 5 { 6 7 var $definitions = array(); 8 var $requires = array(); 9 var $tokens; 10 11 var $symbols; 12 13 14 15 function _parse($source) 16 { 17 if (!function_exists('token_get_all')) { 18 trigger_error('Function "token_get_all" is not defined'); 19 return false; 20 } 21 $source = @preg_match('/<\?php.*'.$source.'.*\?>/', $source)?$source:"<?php ".$source." ?>"; 22 $this->tokens = token_get_all($source); 23 $this->definitions = array(); 24 reset($this->tokens); 25 $previous = array(); 26 $visibility = false; 27 $static = false; 28 $byReference = false; 29 $functionIndent = ''; 30 $docBlock=''; 31 while ($t = current($this->tokens)) { 32 33 if (is_array($t)) { 34 if ($t[0] == T_CLASS || (defined('T_INTERFACE')? $t[0] == T_INTERFACE:false) || $t[0] == T_FUNCTION) { 35 $previous = array_reverse($previous); 36 foreach($previous as $prev) { 37 if ($prev[0] == T_STATIC) { 38 $static = true; 39 } else if ($prev[0] == T_STRING && in_array($prev[1],array('private','public','protected'))) { 40 $visibility = $prev[1]; 41 } else if ($prev[0] == T_PAAMAYIM_NEKUDOTAYIM) { 42 $byReference = true; 43 } else if (((defined('T_DOC_COMMENT')?$prev[0] == T_DOC_COMMENT:false) || T_COMMENT) && !@preg_match('/<\?php.*/',$prev[1]) && @preg_match('/\/\*/',$prev[1])) { 44 $docBlock = isset($prev[1])?$prev[1]:null; 45 break; 46 } else if (isset($prev[1]) && in_array($prev[1],array('private','public','protected'))){ 47 $visibility = $prev[1]; 48 } 49 } 50 $indent=''; 51 if(!empty($docBlock)) { 52 $doclines = split("\n",$docBlock); 53 $lastLine = $doclines[count($doclines)-1]; 54 if (preg_match('/(\s*)?\*/',$lastLine,$matches)) { 55 56 $indent = substr($matches[1],0,strlen($matches[1])-1); 57 58 $doclines[0]=$indent.$doclines[0]; 59 foreach($doclines as $idx=>$line) { 60 $pre = ''; 61 if ($idx>0) { 62 $pre = ' '; 63 } 64 $doclines[$idx] = $pre.trim($line); 65 } 66 $docBlock=implode("\n",$doclines); 67 } 68 } else { 69 $indent = $functionIndent; 70 } 71 $docBlock = str_replace('<?php','',$docBlock); 72 $string = (!empty($docBlock)?$docBlock."\n":'').($visibility?$visibility.' ':'').($static?' static ':''); 73 $this->readDefinition($static, $visibility, $byReference, $docBlock,$string, $indent); 74 $previous = array(); 75 $docBlock = ''; 76 $static = false; 77 $visibility = false; 78 $byReference = false; 79 $functionIndent = ''; 80 $indent = ''; 81 continue; 82 } else if ($t[0] == T_REQUIRE || $t[0] == T_REQUIRE_ONCE || $t[0] == T_INCLUDE || $t[0] == T_INCLUDE_ONCE) { 83 if (!isset($this->requires[$t[1]])) { 84 $this->requires[$t[1]] = array(); 85 } 86 $org = $t; 87 $type= $t[1]; 88 $val=''; 89 next($this->tokens); 90 $t = current($this->tokens); 91 while ($t != '(') { 92 next($this->tokens); 93 $t = current($this->tokens); 94 } 95 next($this->tokens); 96 $t = current($this->tokens); 97 while ($t != ')') { 98 next($this->tokens); 99 if (is_array($t)) { 100 $val.=$t[1]; 101 } else { 102 $val.=$t; 103 } 104 $t = current($this->tokens); 105 } 106 $this->requires[$type][]=$val; 107 $t = $org; 108 } 109 } 110 if ($t[0] != T_WHITESPACE) { 111 $previous[] = $t; 112 } else if ($t[0] == T_WHITESPACE){ 113 $functionIndent.=$t[1]; 114 } 115 116 next($this->tokens); 117 } 118 $this->definitions = array_merge($this->definitions,$this->requires); 119 } 120 function _parseTag(&$tags, $tempTag) 121 { 122 switch($tempTag[0]) { 123 case 'param': 124 if (preg_match('/\$([a-zA-Z0-9_]+)\s+(.*)/s',$tempTag[1],$pmatches)) { 125 if (!isset($tags['params'])) { 126 $tags['params'] = array(); 127 } else if (!is_array($tags['params'])) { 128 $currentValue = $tags['params']; 129 $tags['params'] = array($currentValue); 130 } 131 $tags['params'][$pmatches[1]] = trim($pmatches[2]); 132 } else { 133 134 $tags['_unmatched_'][] = array($tempTag[0],$tempTag[1]); 135 } 136 break; 137 default: 138 if(!empty($tags[$tempTag[0]])) { 139 if(!is_array($tags[$tempTag[0]])) { 140 141 $currentValue = $tags[$tempTag[0]]; 142 $tags[$tempTag[0]] = array($currentValue); 143 } 144 $tags[$tempTag[0]][]=trim($tempTag[1]); 145 } else { 146 $tags[$tempTag[0]]=trim($tempTag[1]); 147 } 148 149 } 150 } 151 function _parseDocBlock($string) 152 { 153 preg_match_all('/\/\*\*\n(\s*\*([^\n]+?\n)+)+.*?\*\//',$string,$matches); 154 $docBlockStructure = array('comment'=>null); 155 if (isset($matches[1][0])) { 156 $docPart = $matches[1][0]; 157 $docPart = preg_replace('/\s*\*\s*/',"\n",$docPart); 158 $docPart = trim($docPart); 159 $commentLines = array(); 160 $tags = array('_unmatched_'=>array()); 161 $docLines = split("\n",$docPart); 162 $inComment = true; 163 $tempTag=array(); 164 foreach ($docLines as $line) { 165 if (preg_match('/^@([a-zA-Z0-9_]+)\s+(.+)$/',$line, $matches)) { 166 if (!empty($tempTag)) { 167 $this->_parseTag(&$tags, $tempTag); 168 } 169 $inComment = false; 170 $tempTag = array($matches[1],$matches[2]); 171 } else if ($inComment) { 172 $commentLines[] = $line; 173 } else { 174 $tempTag[1].="\n".$line; 175 } 176 } 177 if (!empty($tempTag)) { 178 $this->_parseTag(&$tags, $tempTag); 179 } 180 $docBlockStructure['comment'] = trim(implode("\n",$commentLines)); 181 $docBlockStructure['tags'] = $tags; 182 } 183 return $docBlockStructure; 184 } 185 186 function readDefinition($static = false, $visibility = 'public', $byReference = false, $docBlock = '', $string = '', $indent) 187 { 188 $t = current($this->tokens); 189 $definitionType = $t[1]; 190 191 // move past the class/interface/function token 192 193 next($this->tokens); 194 $string.=$definitionType; 195 $string.=$this->skipWhiteAndComments(); 196 197 $t = current($this->tokens); 198 if (!isset($t[1])) { 199 while(!isset($t[1])) { 200 if ($t=='&') { 201 202 $string.=$t; 203 $byReference = true; 204 next($this->tokens); 205 $t = current($this->tokens); 206 207 } 208 } 209 //$definitionType = $t[1]; 210 $string.=$t[1]; 211 212 } else { 213 $string.=$t[1]; 214 } 215 216 $definitionName = $t[1]; 217 218 $this->definitions[] = array( 219 'type' => $definitionType, 220 'name' => $definitionName, 221 'visibility'=>$visibility==false?(substr($definitionName,0,2)=='__')?'private':(substr($definitionName,0,1)=='_'?'protected':false):$visibility, 222 'static'=>$static, 223 'returnByReference'=>$byReference, 224 'docBlock' => $docBlock, 225 'toString' => $string 226 ); 227 228 // move past the name identifier 229 next($this->tokens); 230 231 list($params,$block,$pre,$post) = $this->getCodeBlock(); 232 $default_options = false; 233 $available_options = false; 234 if (preg_match('/\$default_options.*?=.*?(array\(.*?\)).*?;/s',$block,$default_option_matches)) { 235 $default_options_string=$default_option_matches[1]; 236 $default_options_string = preg_replace_callback('/\$([A-Za-z0-9_\->])+/',array(&$this,'_replaceVariablesInsideOptions'),$default_options_string); 237 @eval('$default_options = '.$default_options_string.';'); 238 } 239 if (preg_match('/\$available_options.*?=.*?(array\(.*?\)).*?;/s',$block,$available_option_matches)) { 240 $available_options_string=$available_option_matches[1]; 241 $available_options_string = preg_replace_callback('/\$([A-Za-z0-9_\->])+/',array(&$this,'_replaceVariablesInsideOptions'),$available_options_string); 242 @eval('$available_options = '.$available_options_string.';'); 243 } 244 $string.=$pre.$block.$post; 245 $this->definitions[count($this->definitions)-1]['code'] = $block; 246 $this->definitions[count($this->definitions)-1]['params'] = $params; 247 $this->definitions[count($this->definitions)-1]['toString'] = $string; 248 $this->definitions[count($this->definitions)-1]['default_options'] = $default_options; 249 $this->definitions[count($this->definitions)-1]['available_options'] = $available_options; 250 $strlines = split("\n",$string); 251 foreach ($strlines as $idx=>$line) { 252 $first = substr($line,0,strlen($indent)); 253 if ($first == $indent) { 254 $line = substr($line,strlen($first)); 255 $strlines[$idx] = $line; 256 } 257 } 258 $doclines = split("\n",$docBlock); 259 foreach ($doclines as $idx=>$line) { 260 $first = substr($line,0,strlen($indent)); 261 if ($first == $indent) { 262 $line = substr($line,strlen($first)); 263 $doclines[$idx] = $line; 264 } 265 } 266 $this->definitions[count($this->definitions)-1]['toString'] = implode("\n",$strlines); 267 $this->definitions[count($this->definitions)-1]['docBlock'] = implode("\n",$doclines); 268 } 269 function _replaceVariablesInsideOptions($matches) 270 { 271 $name = $matches[0]; 272 return '"'.str_replace('$','\$',$name).'"'; 273 } 274 function skipWhiteAndComments() 275 { 276 $string = ''; 277 while ($t = current($this->tokens)) { 278 if (is_array($t) && ($t[0] == T_WHITESPACE || (defined('T_DOC_COMMENT')?$t[0] == T_DOC_COMMENT:false) || $t[0] == T_COMMENT)) { 279 next($this->tokens); 280 $string.=$t[1]; 281 } else { 282 return $string; 283 } 284 } 285 } 286 287 function skipCodeBlock() 288 { 289 290 // we go forward until we find the first "{" token 291 292 while(($t = current($this->tokens)) && $t != '{') { 293 next($this->tokens); 294 } 295 // we're about to enter the top level block 296 // which is our class/interface/function definition body 297 $nestingLevel = 0; 298 299 // we go forward keeping the $nestingLevel up-to-date 300 // until we get out of the definition body block 301 while($t = current($this->tokens)) { 302 if ($t == '{') { 303 $nestingLevel++; 304 } 305 306 if ($t == '}') { 307 $nestingLevel--; 308 } 309 310 next($this->tokens); 311 312 if ($nestingLevel == 0) return; 313 } 314 } 315 function getCodeBlock() 316 { 317 $prestring = ''; 318 $poststring = ''; 319 $codeblock = ''; 320 // we go forward until we find the first "{" token 321 $params = array(); 322 $preParam = ''; 323 while(($t = current($this->tokens)) && $t != '{') { 324 if (is_array($t)) { 325 switch ($t[0]) { 326 case T_VARIABLE: 327 $params[]=$preParam.$t[1]; 328 $preParam = ''; 329 break; 330 } 331 $prestring.=$t[1]; 332 } else if (!in_array($t,array(',','(',')'))) { 333 $preParam.=$t; 334 $prestring.=$t; 335 } else { 336 $prestring.=$t; 337 } 338 next($this->tokens); 339 340 } 341 342 // we're about to enter the top level block 343 344 // which is our class/interface/function definition body 345 $nestingLevel = 0; 346 347 // we go forward keeping the $nestingLevel up-to-date 348 // until we get out of the definition body block 349 while($t = current($this->tokens)) { 350 if ($t == '{') { 351 $nestingLevel++; 352 } 353 354 if ($t == '}') { 355 $nestingLevel--; 356 } 357 358 next($this->tokens); 359 360 361 if ($nestingLevel == 0) { 362 $poststring.=$t; 363 return array($params,$codeblock,$prestring,$poststring); 364 } else { 365 if ($t == '{' && $nestingLevel==1) { 366 $prestring.=$t; 367 continue; 368 } 369 $codeblock.=is_array($t)?$t[1]:$t; 370 } 371 } 372 } 373 374 function getDefinitions() 375 { 376 return $this->definitions; 377 } 378 } 379 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Mon Oct 27 12:43:49 2008 | Cross-referenced by PHPXref 0.6 |