fix few Evaluators code

This commit is contained in:
odain
2025-09-04 22:41:14 +02:00
parent 86fe9d6a2b
commit af790269f0
10 changed files with 102 additions and 122 deletions

View File

@@ -16,6 +16,10 @@ class ClassConstFetchEvaluator extends AbstractExprEvaluator {
$sClassName = $oExpr->class->name;
$sProperty = $oExpr->name->name;
if ('class' === $sProperty){
return $sClassName;
}
if (class_exists($sClassName)){
$class = new \ReflectionClass($sClassName);
if (array_key_exists($sProperty, $class->getConstants())) {
@@ -26,10 +30,6 @@ class ClassConstFetchEvaluator extends AbstractExprEvaluator {
}
}
if ('class' === $sProperty){
return $sClassName;
}
return null;
}
}

View File

@@ -5,9 +5,17 @@ namespace Combodo\iTop\PhpParser\Evaluation;
use ModuleFileReaderException;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use ReflectionFunction;
class FuncCallEvaluator extends AbstractExprEvaluator {
public const WHITELIST=[
"function_exists",
"class_exists",
"method_exists"
];
public function GetHandledExpressionType(): ?string {
return FuncCall::class;
}
@@ -15,9 +23,12 @@ class FuncCallEvaluator extends AbstractExprEvaluator {
public function Evaluate(Expr $oExpr): mixed {
/** @var FuncCall $oExpr */
$sFunction = $oExpr->name->name;
$aWhiteList = ["function_exists", "class_exists", "method_exists"];
if (! in_array($sFunction, $aWhiteList)){
if ($oExpr->name instanceof Name){
$sFunction = $oExpr->name->name;
} else {
$sFunction = PhpExpressionEvaluator::GetInstance()->EvaluateExpression($oExpr->name);
}
if (! in_array($sFunction, self::WHITELIST)){
throw new ModuleFileReaderException("FuncCall $sFunction not supported");
}

View File

@@ -4,33 +4,45 @@ namespace Combodo\iTop\PhpParser\Evaluation;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Identifier;
use ReflectionClass;
class MethodCallEvaluator extends AbstractExprEvaluator {
class MethodCallEvaluator extends AbstractExprEvaluator {
public function GetHandledExpressionType(): ?string {
return MethodCall::class;
return null;
}
public function GetHandledExpressionTypes(): ?array {
return [MethodCall::class, Expr\NullsafeMethodCall::class];
}
public function Evaluate(Expr $oExpr): mixed {
/** @var MethodCall $oExpr */
$oVar = PhpExpressionEvaluator::GetInstance()->EvaluateExpression($oExpr->var);
if (is_null($oVar)) {
return null;
}
$aArgs = PhpExpressionEvaluator::GetInstance()->EvaluateExpression($oExpr->args);
$sName = PhpExpressionEvaluator::GetInstance()->EvaluateExpression($oExpr->name);
$oReflectionClass = new ReflectionClass(get_class($oVar));
$oMethods = $oReflectionClass->getMethods();
if (array_key_exists($sName, $oMethods)){
$oMethods = $oMethods[$sName];
if ($oMethods->isPublic()){
return $oMethods->invokeArgs($oVar, $aArgs);
}
$aArgs=[];
foreach ($oExpr->args as $arg){
/** @var \PhpParser\Node\Arg $arg */
$aArgs[]=$arg->value->value;
}
if ($oExpr->name instanceof Identifier){
$sName = $oExpr->name->name;
} else {
$sName = PhpExpressionEvaluator::GetInstance()->EvaluateExpression($oExpr->name);
}
$oReflectionClass = new ReflectionClass(get_class($oVar));
try{
$oMethod = $oReflectionClass->getMethod($sName);
if ($oMethod->isPublic()){
return $oMethod->invokeArgs($oVar, $aArgs);
}
} catch (\ReflectionException $t) {}
return null;
}
}

View File

@@ -1,36 +0,0 @@
<?php
namespace Combodo\iTop\PhpParser\Evaluation;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\NullsafeMethodCall;
use ReflectionClass;
class NullsafeMethodCallEvaluator extends AbstractExprEvaluator {
public function GetHandledExpressionType(): ?string {
return NullsafeMethodCall::class;
}
public function Evaluate(Expr $oExpr): mixed {
/** @var NullsafeMethodCall $oExpr */
$oVar = PhpExpressionEvaluator::GetInstance()->EvaluateExpression($oExpr->var);
if (is_null($oVar)) {
return null;
}
$aArgs = PhpExpressionEvaluator::GetInstance()->EvaluateExpression($oExpr->args);
$sName = PhpExpressionEvaluator::GetInstance()->EvaluateExpression($oExpr->name);
$oReflectionClass = new ReflectionClass(get_class($oVar));
$oMethods = $oReflectionClass->getMethods();
if (array_key_exists($sName, $oMethods)){
$oMethods = $oMethods[$sName];
if ($oMethods->isPublic()){
return $oMethods->invokeArgs($oVar, $aArgs);
}
}
return null;
}
}

View File

@@ -1,35 +0,0 @@
<?php
namespace Combodo\iTop\PhpParser\Evaluation;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\NullsafePropertyFetch;
use ReflectionClass;
class NullsafePropertyFetchEvaluator extends AbstractExprEvaluator {
public function GetHandledExpressionType(): ?string {
return NullsafePropertyFetch::class;
}
public function Evaluate(Expr $oExpr): mixed {
/** @var NullsafePropertyFetch $oExpr */
$oVar = PhpExpressionEvaluator::GetInstance()->EvaluateExpression($oExpr->var);
if (is_null($oVar)) {
return null;
}
$sName = PhpExpressionEvaluator::GetInstance()->EvaluateExpression($oExpr->name);
$oReflectionClass = new ReflectionClass(get_class($oVar));
$oProperties = $oReflectionClass->getProperties();
if (array_key_exists($sName, $oProperties)){
$oProperty = $oProperties[$sName];
if ($oProperty->isPublic()){
return $oProperty->getValue($oVar);
}
}
return null;
}
}

View File

@@ -4,6 +4,7 @@ namespace Combodo\iTop\PhpParser\Evaluation;
use ModuleFileParser;
use ModuleFileReaderException;
use PhpParser\ConstExprEvaluator;
use PhpParser\Node\Expr;
class PhpExpressionEvaluator {
@@ -57,7 +58,24 @@ class PhpExpressionEvaluator {
static::$oInstance = $oInstance;
}
public function EvaluateExpression(Expr $oExpression) : mixed
public function EvaluateExpression(Expr $oExpression, int $iMode=self::LIB_AND_FALLBACK) : mixed
{
if ($iMode==self::ITOP_ALGO){
return $this->EvaluateExpressionLocally($oExpression);
}
if ($iMode==self::LIB_ONLY){
$oConstExprEvaluator = new ConstExprEvaluator();
} else {
$oConstExprEvaluator = new ConstExprEvaluator([$this, "EvaluateExpressionLocally"]);
}
$oConstExprEvaluator->setFunctionsWhitelist(FuncCallEvaluator::WHITELIST);
$oConstExprEvaluator->setStaticcallsWhitelist(StaticCallEvaluator::WHITELIST);
return $oConstExprEvaluator->evaluateDirectly($oExpression);
}
public function EvaluateExpressionLocally(Expr $oExpression) : mixed
{
$sClass = get_class($oExpression);
$oPhpParserEvaluator = static::$aPhpParserEvaluators[$sClass] ?? null;
@@ -79,7 +97,10 @@ class PhpExpressionEvaluator {
return $this->ParseAndEvaluateExpression($sBooleanExpr);
}
public function ParseAndEvaluateExpression(string $sExpr) : mixed
const LIB_AND_FALLBACK=1;
const LIB_ONLY=2;
const ITOP_ALGO=3;
public function ParseAndEvaluateExpression(string $sExpr, int $iMode=self::LIB_AND_FALLBACK) : mixed
{
$sPhpContent = <<<PHP
<?php
@@ -88,7 +109,7 @@ PHP;
try{
$aNodes = ModuleFileParser::GetInstance()->ParsePhpCode($sPhpContent);
$oExpr = $aNodes[0];
return $this->EvaluateExpression($oExpr->expr);
return $this->EvaluateExpression($oExpr->expr, $iMode);
} catch (\Throwable $t) {
throw new ModuleFileReaderException("Eval of '$sExpr' caused an error:".$t->getMessage());
}

View File

@@ -4,44 +4,38 @@ namespace Combodo\iTop\PhpParser\Evaluation;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Identifier;
use ReflectionClass;
class PropertyFetchEvaluator extends AbstractExprEvaluator {
public function GetHandledExpressionType(): ?string {
return PropertyFetch::class;
return null;
}
public function GetHandledExpressionTypes(): ?array {
return [PropertyFetch::class, Expr\NullsafePropertyFetch::class];
}
public function Evaluate(Expr $oExpr): mixed {
/** @var PropertyFetch $oExpr */
$oVar = PhpExpressionEvaluator::GetInstance()->EvaluateExpression($oExpr->var);
if (is_null($oVar)) {
return null;
}
$sName = PhpExpressionEvaluator::GetInstance()->EvaluateExpression($oExpr->name);
$oReflectionClass = new ReflectionClass(get_class($oVar));
if ($oExpr->name instanceof Identifier){
$sName = $oExpr->name->name;
} else {
$sName = PhpExpressionEvaluator::GetInstance()->EvaluateExpression($oExpr->name);
}
$oProperties = $oReflectionClass->getProperties();
if (array_key_exists($sName, $oProperties)){
$oProperty = $oProperties[$sName];
$oReflectionClass = new ReflectionClass(get_class($oVar));
try{
$oProperty = $oReflectionClass->getProperty($sName);
if ($oProperty->isPublic()){
return $oProperty->getValue($oVar);
}
} catch (\ReflectionException $t) {}
return null;
}
$aArgs=[];
$oMethods = $oReflectionClass->getMethods();
if (array_key_exists($sName, $oMethods)){
$oMethod = $oMethods[$sName];
if ($oMethod->isPublic()){
return $oMethod->invokeArgs(null, $aArgs);
}
return null;
}
return null;
}
}

View File

@@ -5,8 +5,14 @@ namespace Combodo\iTop\PhpParser\Evaluation;
use ModuleFileReaderException;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Identifier;
class StaticCallEvaluator extends AbstractExprEvaluator {
public const WHITELIST=[
"SetupInfo::ModuleIsSelected",
"utils::GetItopVersionWikiSyntax"
];
public function GetHandledExpressionType(): ?string {
return StaticCall::class;
}
@@ -15,11 +21,14 @@ class StaticCallEvaluator extends AbstractExprEvaluator {
/** @var StaticCall $oExpr */
$sClassName = $oExpr->class->name;
$sMethodName = $oExpr->name->name;
if ($oExpr->name instanceof Identifier){
$sMethodName = $oExpr->name->name;
} else {
$sMethodName = PhpExpressionEvaluator::GetInstance()->EvaluateExpression($oExpr->name);
}
$aWhiteList = ["SetupInfo::ModuleIsSelected", "utils::GetItopVersionWikiSyntax"];
$sStaticCallDescription = "$sClassName::$sMethodName";
if (! in_array($sStaticCallDescription, $aWhiteList)){
if (! in_array($sStaticCallDescription, self::WHITELIST)){
throw new ModuleFileReaderException("StaticCall $sStaticCallDescription not supported");
}

View File

@@ -4,6 +4,7 @@ namespace Combodo\iTop\PhpParser\Evaluation;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\StaticPropertyFetch;
use PhpParser\Node\Identifier;
class StaticPropertyFetchEvaluator extends AbstractExprEvaluator {
public function GetHandledExpressionType(): ?string {
@@ -14,7 +15,11 @@ class StaticPropertyFetchEvaluator extends AbstractExprEvaluator {
/** @var StaticPropertyFetch $oExpr */
$sClassName = $oExpr->class->name;
$sProperty = $oExpr->name->name;
if ($oExpr->name instanceof Identifier){
$sProperty = $oExpr->name->name;
} else {
$sProperty = PhpExpressionEvaluator::GetInstance()->EvaluateExpression($oExpr->name);
}
if (class_exists($sClassName)){
$class = new \ReflectionClass($sClassName);

View File

@@ -21,7 +21,6 @@ class VariableEvaluator extends AbstractExprEvaluator {
}
$sVarname=$oExpr->name;
global $$sVarname;
return $$sVarname;
}