Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 49
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
ParserNodeFunctionEvaluator
0.00% covered (danger)
0.00%
0 / 49
0.00% covered (danger)
0.00%
0 / 4
650
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 leaveNode
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 1
156
 resolveParamPath
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
42
 resolveArray
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
42
1<?php
2
3use PhpParser\Node;
4use PhpParser\NodeVisitorAbstract;
5use PhpParser\PrettyPrinter\Standard;
6
7// Used to parse access control conditions
8class 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}