Skip to content

Instantly share code, notes, and snippets.

@takyam-git
Created March 7, 2015 07:56
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 takyam-git/f5d2ded7174a29ba1252 to your computer and use it in GitHub Desktop.
Save takyam-git/f5d2ded7174a29ba1252 to your computer and use it in GitHub Desktop.
PHPParserおためし
<?php
define('MY_CONSTANT', 1234);
$constantName = 'MY_CONSTANT2';
define($constantName, 7890);
$globalVariable = 'aiueo';
$GLOBALS['secondGlobal'] = 'abcde';
function globalFunction($arg1, $arg2 = false)
{
global $globalVariable, $globalVariable2;
$localVariable = 2;
$globalVariable2 = 3;
echo $arg1;
return $arg2;
}
require_once __DIR__ . '/someClass.php';
$someClass = new SomeClass(1, 2, 3);
echo $someClass->get(2,$globalVariable);
echo $someClass->plusOne();
echo 'hoge' . foo($piyo) . 'fuga' . 'oho';
if (time() % 2 === 0) {
$globalA = 3;
} elseif (time() % 3 === 0) {
$globalB = 4;
} else {
$globalC = 5;
}
function foo(&$some)
{
$some = 5;
}
foo($new);
----------------------------------------------------------------------------------------------------
array(2) {
[0] =>
string(11) "MY_CONSTANT"
[1] =>
string(13) "$constantName"
}
----------------------------------------------------------------------------------------------------
array(10) {
[0] =>
string(13) "$constantName"
[1] =>
string(15) "$globalVariable"
[2] =>
string(13) "$secondGlobal"
[4] =>
string(16) "$globalVariable2"
[5] =>
string(10) "$someClass"
[6] =>
string(5) "$piyo"
[7] =>
string(8) "$globalA"
[8] =>
string(8) "$globalB"
[9] =>
string(8) "$globalC"
[10] =>
string(4) "$new"
}
array(0) {
}
<?php
require_once __DIR__ . '/../vendor/autoload.php';
$parser = new \PhpParser\Parser(new \PhpParser\Lexer());
$constants = [];
$variables = [];
$phpFile = 'index.php';
$phpCode = file_get_contents($phpFile);
$statements = $parser->parse($phpCode);
foreach ($statements as $statement) {
parseBlock($statement, $constants, $variables);
}
break;
function parseBlock($statement, &$constants, &$variables)
{
// defineを拾う
if ($statement instanceof \PhpParser\Node\Expr\FuncCall) {
if ($statement->name->getFirst() === 'define') {
if (count($statement->args) < 2) {
return;
}
/** @var \PhpParser\Node\Arg $constantNameStmt */
$constantNameStmt = $statement->args[0];
if ($constantNameStmt->value instanceof \PhpParser\Node\Scalar\String) {
$constants[] = $constantNameStmt->value->value;
} else if ($constantNameStmt->value instanceof \PhpParser\Node\Expr\Variable) {
$constants[] = '$' . $constantNameStmt->value->name;
}
} else {
checkMethodCall($statement, $variables);
}
} else if ($statement instanceof \PhpParser\Node\Expr\Assign) {
if ($statement->var instanceof \PhpParser\Node\Expr\Variable) {
$variables[] = '$' . $statement->var->name;
} else if ($statement->var instanceof \PhpParser\Node\Expr\ArrayDimFetch) {
if ($statement->var->var->name === 'GLOBALS') {
$variables[] = '$' . $statement->var->dim->value;
}
}
} else if ($statement instanceof \PhpParser\Node\Stmt\Function_) {
foreach ($statement->stmts as $stmt) {
if ($stmt instanceof \PhpParser\Node\Stmt\Global_) {
/** @var \PhpParser\Node\Expr\Variable $var */
foreach ($stmt->vars as $var) {
$variables[] = '$' . $var->name;
}
}
}
} else if ($statement instanceof \PhpParser\Node\Stmt\If_) {
foreach ($statement->stmts as $stmt) {
parseBlock($stmt, $constants, $variables);
}
foreach ($statement->elseifs as $elseIfStmt) {
foreach ($elseIfStmt->stmts as $stmt) {
parseBlock($stmt, $constants, $variables);
}
}
if ($statement->else) {
foreach ($statement->else->stmts as $stmt) {
parseBlock($stmt, $constants, $variables);
}
}
} else if ($statement instanceof \PhpParser\Node\Expr\Include_) {
//skip
} else if ($statement instanceof \PhpParser\Node\Stmt\Echo_) {
foreach ($statement->exprs as $expr) {
if ($expr instanceof \PhpParser\Node\Expr\MethodCall) {
checkMethodCall($expr, $variables);
} else if ($expr instanceof \PhpParser\Node\Expr\BinaryOp\Concat) {
/** @var \PhpParser\Node\Expr\BinaryOp\Concat $left */
$left = $expr->left;
do {
if ($left->right instanceof \PhpParser\Node\Expr\MethodCall || $left->right instanceof \PhpParser\Node\Expr\FuncCall) {
checkMethodCall($left->right, $variables);
}
if ($left->left instanceof \PhpParser\Node\Expr\MethodCall || $left->left instanceof \PhpParser\Node\Expr\FuncCall) {
checkMethodCall($left->left, $variables);
}
$left = $left->left;
} while ($left instanceof \PhpParser\Node\Expr\BinaryOp\Concat);
}
}
} else {
var_dump($statement);
}
}
/**
* @param \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\FuncCall $node
* @param string[] $variables
*/
function checkMethodCall($node, &$variables)
{
foreach ($node->args as $arg) {
if ($arg->value instanceof \PhpParser\Node\Expr\Variable) {
$variableName = '$' . $arg->value->name;
if (!in_array($variableName, $variables)) {
$variables[] = $variableName;
}
}
}
}
echo str_repeat('-', 100) . PHP_EOL;
var_dump($constants);
echo str_repeat('-', 100) . PHP_EOL;
var_dump(array_unique($variables));
$expectsGlobalVariables = [
'$constantName',
'$globalVariable',
'$secondGlobal',
'$globalVariable2',
'$someClass',
'$new',
'$globalA',
'$globalB',
'$globalC',
'$piyo',
];
var_dump(array_diff($expectsGlobalVariables, $variables));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment