Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
0.00% |
0 / 49 |
|
0.00% |
0 / 4 |
CRAP | |
0.00% |
0 / 1 |
| ParserNodeFunctionEvaluator | |
0.00% |
0 / 49 |
|
0.00% |
0 / 4 |
650 | |
0.00% |
0 / 1 |
| __construct | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
| leaveNode | |
0.00% |
0 / 24 |
|
0.00% |
0 / 1 |
156 | |||
| resolveParamPath | |
0.00% |
0 / 12 |
|
0.00% |
0 / 1 |
42 | |||
| resolveArray | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
42 | |||
| 1 | <?php |
| 2 | |
| 3 | use PhpParser\Node; |
| 4 | use PhpParser\NodeVisitorAbstract; |
| 5 | use PhpParser\PrettyPrinter\Standard; |
| 6 | |
| 7 | // Used to parse access control conditions |
| 8 | class ParserNodeFunctionEvaluator extends NodeVisitorAbstract { |
| 9 | |
| 10 | protected $prettyPrinter; |
| 11 | protected $acReflector; |
| 12 | protected $params = []; // The parameters to be used when calling the methods, as an array |
| 13 | protected $debug; |
| 14 | |
| 15 | public function __construct($params = [], $debug = false){ |
| 16 | $this->acReflector = new ReflectionClass('AccessCondition'); |
| 17 | $this->prettyPrinter = new Standard; |
| 18 | $this->params = $params; |
| 19 | $this->debug = $debug; |
| 20 | } |
| 21 | |
| 22 | public function leaveNode(Node $node) { |
| 23 | // Look for function calls |
| 24 | if ($node instanceof Node\Expr\FuncCall) { |
| 25 | $eval = new Node\Scalar\LNumber(0); |
| 26 | |
| 27 | // Get the method name |
| 28 | $method = $node->name->toString(); |
| 29 | // Get the method arguments |
| 30 | $argNodes = $node->args; |
| 31 | $args = []; |
| 32 | foreach ($argNodes as $arg){ |
| 33 | // In PHP Parser 5.x, args can be either Arg objects or variadic arguments |
| 34 | $argValue = $arg instanceof Node\Arg ? $arg->value : $arg; |
| 35 | $arg_string = $this->prettyPrinter->prettyPrintExpr($argValue); |
| 36 | |
| 37 | // Resolve variables (placeholders and array paths) |
| 38 | if (($argValue instanceof Node\Expr\BinaryOp\Concat) || ($argValue instanceof Node\Expr\ConstFetch)) { |
| 39 | $value = $this->resolveParamPath($arg_string); |
| 40 | // Resolve arrays |
| 41 | } else if ($argValue instanceof Node\Expr\Array_) { |
| 42 | $value = $this->resolveArray($arg); |
| 43 | } else { |
| 44 | $value = $arg_string; |
| 45 | } |
| 46 | $args[] = $value; |
| 47 | } |
| 48 | |
| 49 | if ($this->debug) { |
| 50 | //echo "<pre>"; |
| 51 | error_log("Evaluating method '$method' on \n"); |
| 52 | error_log(print_r($args, true)); |
| 53 | } |
| 54 | |
| 55 | // Call the specified function with the specified arguments. |
| 56 | try{ |
| 57 | $method_handler = $this->acReflector->getMethod($method); |
| 58 | } catch (Exception $e){ |
| 59 | throw new UserFrosting\AuthorizationException("Authorization failed: Access condition method '$method' does not exist."); |
| 60 | } |
| 61 | |
| 62 | $result = $method_handler->invokeArgs(null, $args); |
| 63 | |
| 64 | if ($this->debug){ |
| 65 | error_log("Result: " . ($result ? "1" : "0")); |
| 66 | //echo "</pre>"; |
| 67 | } |
| 68 | |
| 69 | return new Node\Scalar\LNumber($result ? 1 : 0); |
| 70 | } |
| 71 | } |
| 72 | |
| 73 | /* Resolve a parameter path (e.g. "user.id", "post", etc) into its value |
| 74 | */ |
| 75 | private function resolveParamPath($path){ |
| 76 | $pathTokens = explode(".", $path); |
| 77 | $value = $this->params; |
| 78 | foreach ($pathTokens as $token){ |
| 79 | $token = trim($token); |
| 80 | if (is_array($value) && isset($value[$token])){ |
| 81 | $value = $value[$token]; |
| 82 | continue; |
| 83 | } else if (is_object($value) && isset($value->$token)) { |
| 84 | $value = $value->$token; |
| 85 | continue; |
| 86 | } else { |
| 87 | throw new UserFrosting\AuthorizationException("Cannot resolve the path \"$path\". Error at token \"$token\"."); |
| 88 | } |
| 89 | } |
| 90 | return $value; |
| 91 | } |
| 92 | |
| 93 | private function resolveArray($arg){ |
| 94 | $arr = []; |
| 95 | $argValue = $arg instanceof Node\Arg ? $arg->value : $arg; |
| 96 | $items = (array) $argValue->items; |
| 97 | foreach ($items as $item){ |
| 98 | if ($item && $item->key) |
| 99 | $arr[$item->key->value] = $item->value->value; |
| 100 | else if ($item) |
| 101 | $arr[] = $item->value->value; |
| 102 | } |
| 103 | return $arr; |
| 104 | } |
| 105 | |
| 106 | } |