Skip to content

Commit

Permalink
Merge pull request #3 from zef-dev/develop
Browse files Browse the repository at this point in the history
Develop v1.2.0
  • Loading branch information
tolecar authored Dec 27, 2022
2 parents 4f8cf0b + eb15a6c commit 3501f82
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 8 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# CHANGELOG

## 1.2.0 - 2022-12-27

* Allow method calls


## 1.1.0 - 2021-05-14

* Use Smfony 5
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"type": "library",
"description" : "A JUEL like extension for Symfony Expression Language",
"homepage": "https://github.com/zef-dev/zef-expression-language",
"version": "1.1.0",
"version": "1.2.0",
"keywords" : [
"symfony", "expression-language"
],
Expand Down
74 changes: 70 additions & 4 deletions src/Zef/Zel/Symfony/GetAttrNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,17 @@ public function evaluate( $functions, $values)
}

$property = $this->nodes['attribute']->attributes['value'];


if (!$this->_shouldCallMethod($this->attributes['type'], $obj, $property)) {
return null;
}

return $obj->$property;

case self::METHOD_CALL:
$obj = $this->nodes['node']->evaluate($functions, $values);

$method = $this->nodes['attribute']->attributes['value'];

if ( is_null( $obj)) {
return null;
}
Expand All @@ -41,6 +46,10 @@ public function evaluate( $functions, $values)
throw new \RuntimeException(sprintf('Unable to call method "%s" of object "%s".', $this->nodes['attribute']->attributes['value'], \get_class($obj)));
}

if (!$this->_shouldCallMethod($this->attributes['type'], $obj, $method)) {
return null;
}

return $toCall(...array_values($this->nodes['arguments']->evaluate($functions, $values)));

case self::ARRAY_CALL:
Expand All @@ -57,5 +66,62 @@ public function evaluate( $functions, $values)
return $array[$this->nodes['attribute']->evaluate($functions, $values)] ?? null;
}
}

}

private function _shouldCallMethod($callType, $object, $value) {
$isAccessible = 0;
if (is_array($object)) {
return true;
}
if (is_a($object, 'Zef\Zel\IValueAdapter') && is_array($object->get())) {
return true;
}
switch ($callType) {
case self::PROPERTY_CALL:
if (in_array($value, array_keys(get_object_vars($object)))) {
$isAccessible++;
}

if (is_a($object, 'Zef\Zel\IValueAdapter') && in_array($value, array_keys(get_object_vars($object->get())))) {
$isAccessible++;
}

$wrappedClassMethods = get_class_methods($object);

foreach ($wrappedClassMethods as $wrappedClassMethod) {
if (str_contains(strtolower($wrappedClassMethod), strtolower($value))) {
$isAccessible++;
}
}

if (is_a( $object, 'Zef\Zel\IValueAdapter')) {
$originalClassMethods = get_class_methods($object->get());
foreach ($originalClassMethods as $originalClassMethod) {
if (str_contains(strtolower($originalClassMethod), strtolower($value))) {
$isAccessible++;
}
}
}

break;
case self::METHOD_CALL:
if (in_array($value, get_class_methods($object))) {
$isAccessible++;
}

if (is_a( $object, 'Zef\Zel\IValueAdapter') && in_array($value, get_class_methods($object->get()))) {
$isAccessible++;
}

break;
default:
break;
}

if (empty($isAccessible)) {
return false;
}

return true;
}

}
85 changes: 82 additions & 3 deletions tests/CorrectEvaluationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,57 @@ public function getFunctions()
$this->assertEquals( $expected, $expressionLanguage->evaluate( $expression, $values));
}

/**
* @dataProvider provideAlsoNonPublicObjectMethods
*/
public function testResolveWrappedNonPublicProperties( $expression, array $values, $expected)
{
$provider = new class() implements ExpressionFunctionProviderInterface {
public function getFunctions()
{
$functions = [];
$functions[] = ExpressionFunction::fromPhp( 'stripos');
return $functions;
}
};

$expressionLanguage = new ExpressionLanguage( null, [$provider]);
$resolver = new ObjectResolver( $values);
$values = $resolver->get();

$this->assertEquals( $expected, $expressionLanguage->evaluate( $expression, $values));
}

public function testResolveWrappedPrivateMethodCall()
{
$child = new class() {
public function greet($name) { return "Hello $name"; }
};
$user = new class($child)
{
private $test = 'Another Test';

private $_name = 'Test';

private $_child;

public function __construct($child)
{
$this->_child = $child;
}

private function sayHi() { return 'Hi'; }

public function getName() { return $this->_name; }

public function getChild() { return $this->_child; }
};

$this->expectException('RuntimeException');
$el = new ExpressionLanguage();
$el->evaluate('foo.sayHi()', ['foo' => $user]);
}

/**
* @dataProvider provideSimpleValues
* @dataProvider provideArrayValues
Expand Down Expand Up @@ -160,8 +211,36 @@ public function getChild() { return $this->_child; }


return [
['user.getName()', ['user' => $user], 'Test'],
['user.getChild().greet(\'Goofus\')', ['user' => $user], 'Hello Goofus']
['user.get().getName()', ['user' => $user], 'Test'],
['user.get().getChild().greet(\'Goofus\')', ['user' => $user], 'Hello Goofus']
];
}

public function provideAlsoNonPublicObjectMethods()
{
$child = new class() {
public function greet($name) { return "Hello $name"; }
};
$user = new class($child)
{
private $test = 'Another Test';

private $_name = 'Test';

private $_child;

public function __construct($child)
{
$this->_child = $child;
}

public function getName() { return $this->_name; }

public function getChild() { return $this->_child; }
};

return [
['user.test', ['user' => $user], null]
];
}
}
}

0 comments on commit 3501f82

Please sign in to comment.