Passed
Push — master ( 6eecf2...613632 )
by Akpé Aurelle Emmanuel Moïse
01:35
created

NamedArgs::ProcessParams()   A

Complexity

Conditions 6
Paths 7

Size

Total Lines 26
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 17
nc 7
nop 3
dl 0
loc 26
rs 9.0777
c 0
b 0
f 0
1
<?php
2
namespace EZAMA{
3
    class NamedArgs
4
    {
5
        protected $parameters=array();
6
        
7
        public function __construct($mandatory)
8
        {
9
            if (!\is_array($mandatory)) {
10
                throw new \InvalidArgumentException(\sprintf('parameter type must be array, %s given', \gettype($mandatory)));
11
            }
12
            $this->parameters=$mandatory;
13
        }
14
        
15
        protected static function merge(&$arr1, &$arr2)
16
        {
17
            foreach ($arr1 as $k=>$v) {
18
                if (array_key_exists($k, $arr2)) {
19
                    $arr1[$k]=&$arr2[$k];
20
                }
21
            }
22
        }
23
        
24
        protected static function format($OneDarray)
25
        {
26
            if (!\is_array($OneDarray)) {
27
                return '';
28
            }
29
            if (\count($OneDarray)>1) {
30
                $end=array_pop($OneDarray);
31
                return \join(',', $OneDarray)." and $end ";
32
            } else {
33
                return array_pop($OneDarray);
34
            }
35
        }
36
        
37
        protected static function throwError($error)
38
        {
39
            $error=(string)($error);
40
            if (\version_compare(\PHP_VERSION, '7.0.0') < 0) {
41
                \trigger_error($error, \E_USER_ERROR);
42
            } else {
43
                throw new \Error($error);
44
            }
45
        }
46
         
47
        
48
        protected static function &ProcessParams(&$argument, $required, $default)
49
        {
50
            $missing=array();
51
            if (!\is_array($argument)) {
52
                return \false;
53
            }
54
            $argument=array_intersect_key($argument, $default);//keep only predefined names
55
            //check for missing required parameters
56
            foreach ($required as $k=>$v) {
57
                if (!array_key_exists($v, $argument)) {
58
                    $missing[]=$v;
59
                }
60
            }
61
62
            if (!empty($missing)) {
63
                $function=\debug_backtrace();
64
                $function=\end($function);
65
                $function=$function['function'];
66
                $cm=\count($missing);
67
                $error=\call_user_func_array('sprintf', array('Function  %s\'s  Required '.($cm>1?'parameters %s are':'parameter %s is').' missing',$function,NamedArgs::format($missing)));
68
                self::throwError($error);
69
            }
70
            
71
            
72
            self::merge($default, $argument);//assign given values to parameters while keeping references
73
            return $default;
74
        }
75
        
76
        public function &getParams($required, $default)
77
        {
78
            if (self::is_valid_associative($this->parameters)) {
79
                return self::ProcessParams($this->parameters, $required, $default);
80
            } else {
81
                $cp=\count($this->parameters);
82
                if ($cp>=\count($required)) {
83
                    foreach (array_keys($default) as $k=>$v) {
84
                        if ($k===$cp) {
85
                            break;
86
                        }
87
                        $default[$v]=&$this->parameters[$k];
88
                    }
89
                    return self::ProcessParams($default, $required, $default);
90
                } else {
91
                    $function=\debug_backtrace();
92
                    $function=\end($function);
93
                    $function=$function['function'];
94
95
                    self::throwError(\sprintf('Function  %s : Two few parameters supplied', $function));
96
                }
97
            }
98
        }
99
        
100
        protected static function is_valid_associative($array)
101
        {
102
            if (!\is_array($array)) {
103
                return \false;
104
            }
105
            foreach ($array as $k=>$v) {
106
                if (!\preg_match('#^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$#', (string)$k)) {
107
                    return \false;
108
                }
109
            }
110
            return \true;
111
        }
112
        
113
        public static function __callStatic($name, $mandatory)
114
        {
115
            if (empty($mandatory)) {
116
                $mandatory[0]=[];
117
            }
118
            
119
            if ($mandatory[0] instanceof NamedArgs) {
120
                return self::func($name, $mandatory[0]);
121
            } elseif (\is_array($mandatory[0])) {
122
                return self::func($name, new self($mandatory[0]));
123
            }
124
            return \false;
125
        }
126
        
127
        
128
        protected static function func($func, NamedArgs $mandatory)
129
        {
130
            $args=&$mandatory->parameters;
131
            return self::processParamsAndArgs($func, $args);
132
        }
133
        
134
        protected static function getReflection(&$func)
135
        {
136
            if (!\is_string($func)) {
137
                throw new \BadFunctionCallException('Try to call undefined Function');
138
            }
139
            try {
140
                $func = new \reflectionFunction($func);
141
            } catch (\ReflectionException $e) {
142
                throw new \BadFunctionCallException('Try to call undefined Function');
143
            }
144
        }
145
        
146
        protected static function getValues(&$func, &$params, $paramsArgs, &$args, $associative)
147
        {
148
            foreach ((array)$params as $k=> $param) {
149
                $key=$associative?$param->name:$k;
150
                if (array_key_exists($key, $args)) {
151
                    $paramsArgs[]=&$args[$key];
152
                } else {
153
                    self::elseifGetValues($func, $param, $paramsArgs);
154
                }
155
            }
156
            return $paramsArgs;
157
        }
158
        
159
        protected static function handleOptional($notOptional, $func, $param)
160
        {
161
            if ($notOptional) {
162
                self::throwError(\sprintf('Function  %s\'s required parameter %s is missing', $func, $param));
163
            }
164
        }
165
        
166
        protected static function getParamDefaultValue(\reflectionParameter $param)
167
        {
168
            return $param->getDefaultValueConstantName()?\constant($param->getDefaultValueConstantName()):$param->getDefaultValue();
169
        }
170
        
171
        protected static function canGetParamDefaultValue(\reflectionFunction $func, \reflectionParameter $param)
172
        {
173
            return !$func->isInternal()&&($param->isDefaultValueAvailable()||$param->isDefaultValueConstant());
174
        }
175
        
176
        
177
        protected static function elseifGetValues(\reflectionFunction $func, \reflectionParameter $param, &$paramsArgs)
178
        {
179
            if (self::canGetParamDefaultValue($func, $param)) {
180
                $paramsArgs[] = self::getParamDefaultValue($param);
181
            } elseif ($param->allowsNull()) {
182
                $paramsArgs[]=null;
183
            } else {
184
                self::handleOptional(!$param->isOptional(), (string)$func->name, (string)$param->name);
185
            }
186
        }
187
188
        protected static function processParamsAndArgs($func, $args)
189
        {
190
            self::getReflection($func);
191
            $paramsArgs = array();
192
            $params =$func->getParameters();
193
            return $func->invokeArgs(self::getValues($func, $params, $paramsArgs, $args, self::is_valid_associative($args)));
194
        }
195
    }
196
197
}
198