1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* @author Patsura Dmitry https://github.com/ovr <[email protected]> |
4
|
|
|
*/ |
5
|
|
|
|
6
|
|
|
namespace PHPSA\Compiler\Expression; |
7
|
|
|
|
8
|
|
|
use PHPSA\Check; |
9
|
|
|
use PHPSA\CompiledExpression; |
10
|
|
|
use PHPSA\Context; |
11
|
|
|
use PHPSA\Definition\ClassDefinition; |
12
|
|
|
|
13
|
|
|
class MethodCall extends AbstractExpressionCompiler |
14
|
|
|
{ |
15
|
|
|
protected $name = 'PhpParser\Node\Expr\MethodCall'; |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* @param \PhpParser\Node\Expr\MethodCall $expr |
19
|
|
|
* @param Context $context |
20
|
|
|
* @return CompiledExpression |
21
|
|
|
*/ |
22
|
2 |
|
protected function compile($expr, Context $context) |
23
|
|
|
{ |
24
|
2 |
|
$expressionCompiler = $context->getExpressionCompiler(); |
25
|
2 |
|
$methodNameCE = $expressionCompiler->compile($expr->name); |
26
|
|
|
|
27
|
2 |
|
$compiledArguments = $this->parseArgs($expr->args, $context); |
28
|
|
|
|
29
|
2 |
|
$leftCE = $expressionCompiler->compile($expr->var); |
30
|
2 |
|
if ($leftCE->canBeObject()) { |
31
|
|
|
/** @var ClassDefinition $calledObject */ |
32
|
2 |
|
$calledObject = $leftCE->getValue(); |
33
|
2 |
|
if ($calledObject instanceof ClassDefinition) { |
34
|
2 |
|
$methodName = $methodNameCE->isString() ? $methodNameCE->getValue() : false; |
35
|
2 |
|
if ($methodName) { |
36
|
2 |
|
if (!$calledObject->hasMethod($methodName, true)) { |
37
|
|
|
$context->notice( |
38
|
|
|
'language_error', |
39
|
|
|
sprintf('Method %s() does not exist in %s scope', $methodName, $calledObject->getName()), |
40
|
|
|
$expr |
41
|
|
|
); |
42
|
|
|
|
43
|
|
|
//it's needed to exit |
44
|
|
|
return new CompiledExpression(); |
45
|
|
|
} |
46
|
|
|
|
47
|
2 |
|
$method = $calledObject->getMethod($methodName, true); |
48
|
2 |
|
if (!$method) { |
49
|
|
|
$context->debug('getMethod is not working', $expr); |
50
|
|
|
return new CompiledExpression(); |
51
|
|
|
} |
52
|
|
|
|
53
|
2 |
|
if ($method->isStatic()) { |
54
|
2 |
|
$context->notice( |
55
|
2 |
|
'language_error', |
56
|
2 |
|
"Method {$methodName}() is static but called like a class method", |
57
|
|
|
$expr |
58
|
2 |
|
); |
59
|
2 |
|
} |
60
|
|
|
|
61
|
2 |
|
return $method->run(clone $context, $compiledArguments); |
62
|
|
|
} |
63
|
|
|
} |
64
|
2 |
|
return new CompiledExpression(); |
65
|
|
|
} else { |
66
|
|
|
$context->notice( |
67
|
|
|
'language_error', |
68
|
|
|
sprintf('$%s is not an object and cannot be called like this', $expr->var->name), |
|
|
|
|
69
|
|
|
$expr->var, |
70
|
|
|
Check::CHECK_ALPHA |
71
|
|
|
); |
72
|
|
|
} |
73
|
|
|
|
74
|
|
|
$context->debug('[Unknown] @todo MethodCall', $expr); |
75
|
|
|
return new CompiledExpression(); |
76
|
|
|
} |
77
|
|
|
|
78
|
|
|
/** |
79
|
|
|
* @param \PhpParser\Node\Arg[] $arguments |
80
|
|
|
* @param Context $context |
81
|
|
|
* @return CompiledExpression[] |
82
|
|
|
*/ |
83
|
2 |
|
protected function parseArgs(array $arguments, Context $context) |
84
|
|
|
{ |
85
|
2 |
|
$compiled = []; |
86
|
|
|
|
87
|
2 |
|
if ($arguments) { |
|
|
|
|
88
|
2 |
|
foreach ($arguments as $argument) { |
89
|
2 |
|
$compiled[] = $context->getExpressionCompiler()->compile($argument->value); |
90
|
2 |
|
} |
91
|
2 |
|
} |
92
|
|
|
|
93
|
2 |
|
return $compiled; |
94
|
|
|
} |
95
|
|
|
} |
96
|
|
|
|
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.
If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.