| Total Complexity | 48 |
| Total Lines | 191 |
| Duplicated Lines | 0 % |
| Changes | 0 | ||
Complex classes like NamedArgs often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use NamedArgs, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 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) |
||
| 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) |
||
| 194 | } |
||
| 195 | } |
||
| 196 | |||
| 197 | } |
||
| 198 |