Skip to content

Instantly share code, notes, and snippets.

@Pamblam
Created April 20, 2017 13:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Pamblam/3b6c60de61dc90d777c0221520c64fcd to your computer and use it in GitHub Desktop.
Save Pamblam/3b6c60de61dc90d777c0221520c64fcd to your computer and use it in GitHub Desktop.
<?php
/**
* Given a string of PHP code, this will provide a list of classes, their
* constructors and the line number they're on. Used for programmatically
* updating older code using PHP4 style constructors to PHP7
*/
class classParser{
private $code;
private $tokens = array();
public function __construct($code){
$this->code = $code;
$this->getTokens();
}
public function getClasses(){
$classes = array();
foreach($this->tokens as $ti=>$token){
if(!is_array($token)) continue;
if($token['token'] === "T_CLASS"){
$className = $this->getClassName($ti);
$const = $this->getConstructor($ti, $className);
$classes[] = array(
"name" => $className,
"constructor" => $const['name'],
"constructorLine" => $const['line'],
"signature_def" => $this->getConstructorSignatureWithVars($const['name'], $const['line']),
"signature_use" => $this->getConstructorSignature($const['name'], $const['line'])
);
}
}
return $classes;
}
private function getConstructorSignature($name, $line){
$fullConstr = $this->getConstructorSignatureWithVars($name, $line);
$cParts = explode(",", trim($fullConstr, " ()"));
$varNames = array();
foreach($cParts as $part){
$var = explode("=", $part);
$varname = trim($var[0]);
if(substr($varname, 0, 1) !== "$") continue;
$varNames[] = trim($var[0]);
}
return "(".implode(", ", $varNames).")";
}
private function getConstructorSignatureWithVars($name, $line){
$lines = explode("\n", $this->code);
$startpos = strpos($lines[$line-1], $name) + strlen($name);
$endpos = strpos($lines[$line-1], ")")+1;
return substr($lines[$line-1], $startpos, $endpos-$startpos);
}
private function getTokens(){
$tokens = token_get_all($this->code);
foreach($tokens as $k=>$v){
if(is_array($v)){
$this->tokens[] = array(
"token" => token_name($v[0]),
"string" => $v[1],
"line" => $v[2]
);
}else $this->tokens[] = $v;
}
}
private function getConstructor($tokenIndex, $classname){
for($i=$tokenIndex+2; $i<count($this->tokens); $i++){
if(!is_array($this->tokens[$i])) continue;
if($this->tokens[$i]['token'] === "T_CLASS") return false;
if(!is_array($this->tokens[$i])) continue;
if($this->tokens[$i]['token'] !== "T_FUNCTION") continue;
$constructorName = $this->getFunctName($i);
if(strtolower($constructorName) === strtolower($classname))
return array('name'=>$constructorName, 'line'=>$this->tokens[$i]['line']);
if(strtolower($constructorName) === "__construct")
return array('name'=>$constructorName, 'line'=>$this->tokens[$i]['line']);
}
return false;
}
private function getFunctName($tokenIndex){
if(empty($this->tokens[$tokenIndex])) return false;
if($this->tokens[$tokenIndex]['token'] !== "T_FUNCTION") return false;
if($this->tokens[$tokenIndex+1]['token'] !== "T_WHITESPACE") return false;
if($this->tokens[$tokenIndex+2]['token'] !== "T_STRING") return false;
return $this->tokens[$tokenIndex+2]['string'];
}
private function getClassName($tokenIndex){
if(empty($this->tokens[$tokenIndex])) return false;
if($this->tokens[$tokenIndex]['token'] !== "T_CLASS") return false;
if($this->tokens[$tokenIndex+1]['token'] !== "T_WHITESPACE") return false;
if($this->tokens[$tokenIndex+2]['token'] !== "T_STRING") return false;
return $this->tokens[$tokenIndex+2]['string'];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment