| Conditions | 49 |
| Paths | 48 |
| Total Lines | 250 |
| Code Lines | 146 |
| Lines | 0 |
| Ratio | 0 % |
| Changes | 0 | ||
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
| 1 | <?php |
||
| 117 | public static function getFunctionCalls($source, $line, $function) |
||
| 118 | { |
||
| 119 | static $up = array( |
||
| 120 | '(' => true, |
||
| 121 | '[' => true, |
||
| 122 | '{' => true, |
||
| 123 | T_CURLY_OPEN => true, |
||
| 124 | T_DOLLAR_OPEN_CURLY_BRACES => true, |
||
| 125 | ); |
||
| 126 | static $down = array( |
||
| 127 | ')' => true, |
||
| 128 | ']' => true, |
||
| 129 | '}' => true, |
||
| 130 | ); |
||
| 131 | static $modifiers = array( |
||
| 132 | '!' => true, |
||
| 133 | '@' => true, |
||
| 134 | '~' => true, |
||
| 135 | '+' => true, |
||
| 136 | '-' => true, |
||
| 137 | ); |
||
| 138 | static $identifier = array( |
||
| 139 | T_DOUBLE_COLON => true, |
||
| 140 | T_STRING => true, |
||
| 141 | T_NS_SEPARATOR => true, |
||
| 142 | ); |
||
| 143 | |||
| 144 | if (KINT_PHP56) { |
||
| 145 | self::$operator[T_POW] = true; |
||
| 146 | self::$operator[T_POW_EQUAL] = true; |
||
| 147 | } |
||
| 148 | |||
| 149 | if (KINT_PHP70) { |
||
| 150 | self::$operator[T_SPACESHIP] = true; |
||
| 151 | } |
||
| 152 | |||
| 153 | if (KINT_PHP74) { |
||
| 154 | self::$operator[T_COALESCE_EQUAL] = true; |
||
| 155 | } |
||
| 156 | |||
| 157 | $tokens = \token_get_all($source); |
||
| 158 | $cursor = 1; |
||
| 159 | $function_calls = array(); |
||
| 160 | /** @var array<int, null|array|string> Performance optimization preventing backwards loops */ |
||
| 161 | $prev_tokens = array(null, null, null); |
||
| 162 | |||
| 163 | if (\is_array($function)) { |
||
| 164 | $class = \explode('\\', $function[0]); |
||
| 165 | $class = \strtolower(\end($class)); |
||
| 166 | $function = \strtolower($function[1]); |
||
| 167 | } else { |
||
| 168 | $class = null; |
||
| 169 | $function = \strtolower($function); |
||
| 170 | } |
||
| 171 | |||
| 172 | // Loop through tokens |
||
| 173 | foreach ($tokens as $index => $token) { |
||
| 174 | if (!\is_array($token)) { |
||
| 175 | continue; |
||
| 176 | } |
||
| 177 | |||
| 178 | // Count newlines for line number instead of using $token[2] |
||
| 179 | // since certain situations (String tokens after whitespace) may |
||
| 180 | // not have the correct line number unless you do this manually |
||
| 181 | $cursor += \substr_count($token[1], "\n"); |
||
| 182 | if ($cursor > $line) { |
||
| 183 | break; |
||
| 184 | } |
||
| 185 | |||
| 186 | // Store the last real tokens for later |
||
| 187 | if (isset(self::$ignore[$token[0]])) { |
||
| 188 | continue; |
||
| 189 | } |
||
| 190 | |||
| 191 | $prev_tokens = array($prev_tokens[1], $prev_tokens[2], $token); |
||
| 192 | |||
| 193 | // Check if it's the right type to be the function we're looking for |
||
| 194 | if (T_STRING !== $token[0] || \strtolower($token[1]) !== $function) { |
||
| 195 | continue; |
||
| 196 | } |
||
| 197 | |||
| 198 | // Check if it's a function call |
||
| 199 | $nextReal = self::realTokenIndex($tokens, $index); |
||
| 200 | if (!isset($nextReal, $tokens[$nextReal]) || '(' !== $tokens[$nextReal]) { |
||
| 201 | continue; |
||
| 202 | } |
||
| 203 | |||
| 204 | // Check if it matches the signature |
||
| 205 | if (null === $class) { |
||
| 206 | if ($prev_tokens[1] && \in_array($prev_tokens[1][0], array(T_DOUBLE_COLON, T_OBJECT_OPERATOR), true)) { |
||
| 207 | continue; |
||
| 208 | } |
||
| 209 | } else { |
||
| 210 | if (!$prev_tokens[1] || T_DOUBLE_COLON !== $prev_tokens[1][0]) { |
||
| 211 | continue; |
||
| 212 | } |
||
| 213 | |||
| 214 | if (!$prev_tokens[0] || T_STRING !== $prev_tokens[0][0] || \strtolower($prev_tokens[0][1]) !== $class) { |
||
| 215 | continue; |
||
| 216 | } |
||
| 217 | } |
||
| 218 | |||
| 219 | $inner_cursor = $cursor; |
||
| 220 | $depth = 1; // The depth respective to the function call |
||
| 221 | $offset = $nextReal + 1; // The start of the function call |
||
| 222 | $instring = false; // Whether we're in a string or not |
||
| 223 | $realtokens = false; // Whether the current scope contains anything meaningful or not |
||
| 224 | $paramrealtokens = false; // Whether the current parameter contains anything meaningful |
||
| 225 | $params = array(); // All our collected parameters |
||
| 226 | $shortparam = array(); // The short version of the parameter |
||
| 227 | $param_start = $offset; // The distance to the start of the parameter |
||
| 228 | |||
| 229 | // Loop through the following tokens until the function call ends |
||
| 230 | while (isset($tokens[$offset])) { |
||
| 231 | $token = $tokens[$offset]; |
||
| 232 | |||
| 233 | // Ensure that the $inner_cursor is correct and |
||
| 234 | // that $token is either a T_ constant or a string |
||
| 235 | if (\is_array($token)) { |
||
| 236 | $inner_cursor += \substr_count($token[1], "\n"); |
||
| 237 | } |
||
| 238 | |||
| 239 | if (!isset(self::$ignore[$token[0]]) && !isset($down[$token[0]])) { |
||
| 240 | $paramrealtokens = $realtokens = true; |
||
| 241 | } |
||
| 242 | |||
| 243 | // If it's a token that makes us to up a level, increase the depth |
||
| 244 | if (isset($up[$token[0]])) { |
||
| 245 | if (1 === $depth) { |
||
| 246 | $shortparam[] = $token; |
||
| 247 | $realtokens = false; |
||
| 248 | } |
||
| 249 | |||
| 250 | ++$depth; |
||
| 251 | } elseif (isset($down[$token[0]])) { |
||
| 252 | --$depth; |
||
| 253 | |||
| 254 | // If this brings us down to the parameter level, and we've had |
||
| 255 | // real tokens since going up, fill the $shortparam with an ellipsis |
||
| 256 | if (1 === $depth) { |
||
| 257 | if ($realtokens) { |
||
| 258 | $shortparam[] = '...'; |
||
| 259 | } |
||
| 260 | $shortparam[] = $token; |
||
| 261 | } |
||
| 262 | } elseif ('"' === $token[0]) { |
||
| 263 | // Strings use the same symbol for up and down, but we can |
||
| 264 | // only ever be inside one string, so just use a bool for that |
||
| 265 | if ($instring) { |
||
| 266 | --$depth; |
||
| 267 | if (1 === $depth) { |
||
| 268 | $shortparam[] = '...'; |
||
| 269 | } |
||
| 270 | } else { |
||
| 271 | ++$depth; |
||
| 272 | } |
||
| 273 | |||
| 274 | $instring = !$instring; |
||
|
|
|||
| 275 | |||
| 276 | $shortparam[] = '"'; |
||
| 277 | } elseif (1 === $depth) { |
||
| 278 | if (',' === $token[0]) { |
||
| 279 | $params[] = array( |
||
| 280 | 'full' => \array_slice($tokens, $param_start, $offset - $param_start), |
||
| 281 | 'short' => $shortparam, |
||
| 282 | ); |
||
| 283 | $shortparam = array(); |
||
| 284 | $paramrealtokens = false; |
||
| 285 | $param_start = $offset + 1; |
||
| 286 | } elseif (T_CONSTANT_ENCAPSED_STRING === $token[0] && \strlen($token[1]) > 2) { |
||
| 287 | $shortparam[] = $token[1][0].'...'.$token[1][0]; |
||
| 288 | } else { |
||
| 289 | $shortparam[] = $token; |
||
| 290 | } |
||
| 291 | } |
||
| 292 | |||
| 293 | // Depth has dropped to 0 (So we've hit the closing paren) |
||
| 294 | if ($depth <= 0) { |
||
| 295 | if ($paramrealtokens) { |
||
| 296 | $params[] = array( |
||
| 297 | 'full' => \array_slice($tokens, $param_start, $offset - $param_start), |
||
| 298 | 'short' => $shortparam, |
||
| 299 | ); |
||
| 300 | } |
||
| 301 | |||
| 302 | break; |
||
| 303 | } |
||
| 304 | |||
| 305 | ++$offset; |
||
| 306 | } |
||
| 307 | |||
| 308 | // If we're not passed (or at) the line at the end |
||
| 309 | // of the function call, we're too early so skip it |
||
| 310 | if ($inner_cursor < $line) { |
||
| 311 | continue; |
||
| 312 | } |
||
| 313 | |||
| 314 | // Format the final output parameters |
||
| 315 | foreach ($params as &$param) { |
||
| 316 | $name = self::tokensFormatted($param['short']); |
||
| 317 | $expression = false; |
||
| 318 | foreach ($name as $token) { |
||
| 319 | if (self::tokenIsOperator($token)) { |
||
| 320 | $expression = true; |
||
| 321 | break; |
||
| 322 | } |
||
| 323 | } |
||
| 324 | |||
| 325 | $param = array( |
||
| 326 | 'name' => self::tokensToString($name), |
||
| 327 | 'path' => self::tokensToString(self::tokensTrim($param['full'])), |
||
| 328 | 'expression' => $expression, |
||
| 329 | ); |
||
| 330 | } |
||
| 331 | |||
| 332 | // Get the modifiers |
||
| 333 | --$index; |
||
| 334 | |||
| 335 | while (isset($tokens[$index])) { |
||
| 336 | if (!isset(self::$ignore[$tokens[$index][0]]) && !isset($identifier[$tokens[$index][0]])) { |
||
| 337 | break; |
||
| 338 | } |
||
| 339 | |||
| 340 | --$index; |
||
| 341 | } |
||
| 342 | |||
| 343 | $mods = array(); |
||
| 344 | |||
| 345 | while (isset($tokens[$index])) { |
||
| 346 | if (isset(self::$ignore[$tokens[$index][0]])) { |
||
| 347 | --$index; |
||
| 348 | continue; |
||
| 349 | } |
||
| 350 | |||
| 351 | if (isset($modifiers[$tokens[$index][0]])) { |
||
| 352 | $mods[] = $tokens[$index]; |
||
| 353 | --$index; |
||
| 354 | continue; |
||
| 355 | } |
||
| 356 | |||
| 357 | break; |
||
| 358 | } |
||
| 359 | |||
| 360 | $function_calls[] = array( |
||
| 361 | 'parameters' => $params, |
||
| 362 | 'modifiers' => $mods, |
||
| 363 | ); |
||
| 364 | } |
||
| 365 | |||
| 366 | return $function_calls; |
||
| 367 | } |
||
| 474 |