|
16 | 16 | use PhpParser\Node\Expr\AssignOp; |
17 | 17 | use PhpParser\Node\Expr\AssignRef; |
18 | 18 | use PhpParser\Node\Expr\BinaryOp; |
| 19 | +use PhpParser\Node\Expr\BinaryOp\BooleanAnd; |
19 | 20 | use PhpParser\Node\Expr\BinaryOp\Coalesce; |
20 | 21 | use PhpParser\Node\Expr\BinaryOp\Equal; |
21 | 22 | use PhpParser\Node\Expr\BinaryOp\Identical; |
@@ -427,33 +428,106 @@ protected function refactorHasValue(StaticCall $call): ?Node |
427 | 428 |
|
428 | 429 | if ($call->isFirstClassCallable()) { |
429 | 430 | $valueVariable = new Variable('value'); |
| 431 | + $valueVariableArg = new Arg($valueVariable); |
| 432 | + |
| 433 | + $tryFromNotNull = $makeTryFromNotNull($valueVariableArg); |
| 434 | + |
| 435 | + $enumScalarType = $this->enumScalarTypeFromClassName($class); |
| 436 | + if ($enumScalarType === 'int') { |
| 437 | + $expr = new BooleanAnd( |
| 438 | + new FuncCall(new Name('is_int'), [$valueVariableArg]), |
| 439 | + $tryFromNotNull |
| 440 | + ); |
| 441 | + } elseif ($enumScalarType === 'string') { |
| 442 | + $expr = new BooleanAnd( |
| 443 | + new FuncCall(new Name('is_string'), [$valueVariableArg]), |
| 444 | + $tryFromNotNull |
| 445 | + ); |
| 446 | + } else { |
| 447 | + $expr = $tryFromNotNull; |
| 448 | + } |
430 | 449 |
|
431 | 450 | return new ArrowFunction([ |
432 | 451 | 'static' => true, |
433 | 452 | 'params' => [new Param($valueVariable, null, 'mixed')], |
434 | 453 | 'returnType' => 'bool', |
435 | | - 'expr' => $makeTryFromNotNull(new Arg($valueVariable)), |
| 454 | + 'expr' => $expr, |
436 | 455 | ]); |
437 | 456 | } |
438 | 457 |
|
439 | 458 | $args = $call->args; |
440 | 459 | $firstArg = $args[0] ?? null; |
441 | 460 | if ($firstArg instanceof Arg) { |
442 | 461 | $firstArgValue = $firstArg->value; |
| 462 | + |
443 | 463 | if ( |
444 | 464 | $firstArgValue instanceof ClassConstFetch |
445 | 465 | && $firstArgValue->class->toString() === $class->toString() |
446 | 466 | ) { |
447 | 467 | return new ConstFetch(new Name('true')); |
448 | 468 | } |
449 | 469 |
|
| 470 | + $firstArgType = $this->getType($firstArgValue); |
| 471 | + |
| 472 | + $enumScalarType = $this->enumScalarTypeFromClassName($class); |
| 473 | + if ($enumScalarType === 'int') { |
| 474 | + $firstArgTypeIsInt = $firstArgType->isInteger(); |
| 475 | + if ($firstArgTypeIsInt->yes()) { |
| 476 | + return $makeTryFromNotNull($firstArg); |
| 477 | + } |
| 478 | + |
| 479 | + if ($firstArgTypeIsInt->no()) { |
| 480 | + return new ConstFetch(new Name('false')); |
| 481 | + } |
| 482 | + |
| 483 | + return new BooleanAnd( |
| 484 | + new FuncCall(new Name('is_int'), [$firstArg]), |
| 485 | + $makeTryFromNotNull($firstArg) |
| 486 | + ); |
| 487 | + } |
| 488 | + if ($enumScalarType === 'string') { |
| 489 | + $firstArgTypeIsString = $firstArgType->isString(); |
| 490 | + if ($firstArgTypeIsString->yes()) { |
| 491 | + return $makeTryFromNotNull($firstArg); |
| 492 | + } |
| 493 | + |
| 494 | + if ($firstArgTypeIsString->no()) { |
| 495 | + return new ConstFetch(new Name('false')); |
| 496 | + } |
| 497 | + |
| 498 | + return new BooleanAnd( |
| 499 | + new FuncCall(new Name('is_string'), [$firstArg]), |
| 500 | + $makeTryFromNotNull($firstArg) |
| 501 | + ); |
| 502 | + } |
| 503 | + |
450 | 504 | return $makeTryFromNotNull($firstArg); |
451 | 505 | } |
452 | 506 | } |
453 | 507 |
|
454 | 508 | return null; |
455 | 509 | } |
456 | 510 |
|
| 511 | + protected function enumScalarTypeFromClassName(Name $class): ?string |
| 512 | + { |
| 513 | + $type = $this->getType($class); |
| 514 | + if (! $type instanceof FullyQualifiedObjectType) { |
| 515 | + return null; |
| 516 | + } |
| 517 | + |
| 518 | + $classReflection = $type->getClassReflection(); |
| 519 | + if (! $classReflection) { |
| 520 | + return null; |
| 521 | + } |
| 522 | + |
| 523 | + $nativeReflection = $classReflection->getNativeReflection(); |
| 524 | + if (! $nativeReflection instanceof \ReflectionClass) { |
| 525 | + return null; |
| 526 | + } |
| 527 | + |
| 528 | + return $this->enumScalarType($nativeReflection->getConstants()); |
| 529 | + } |
| 530 | + |
457 | 531 | /** |
458 | 532 | * @see Enum::__callStatic() |
459 | 533 | * @see Enum::__call() |
|
0 commit comments