Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

namespace Rector\Tests\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;

final class SkipStringCasted
{
public function run($value)
{
explode(
',',
(string) $value ? $_SERVER['REMOTE_ADDR'] : $_SERVER['HTTP_X_FORWARDED_FOR'] ?? ''
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

namespace Rector\Tests\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;

final class TernaryWithInts
{
public function run($value)
{
explode(
',',
(string) $value ? 100 : 500
);
}
}

?>
-----
<?php

declare(strict_types=1);

namespace Rector\Tests\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;

final class TernaryWithInts
{
public function run($value)
{
explode(
',',
(string) ((string) $value ? 100 : 500)
);
}
}

?>
48 changes: 45 additions & 3 deletions rules/Php81/NodeManipulator/NullToStrictStringIntConverter.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
use PHPStan\Type\Type;
use PHPStan\Type\UnionType;
use Rector\NodeAnalyzer\PropertyFetchAnalyzer;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\NodeTypeResolver;
use Rector\PhpParser\Node\Value\ValueResolver;

Expand Down Expand Up @@ -53,12 +54,18 @@ public function convertIfNull(
}

$argValue = $args[$position]->value;

if ($this->valueResolver->isNull($argValue)) {
$args[$position]->value = $targetType === 'string' ? new String_('') : new Int_(0);
$funcCall->args = $args;
return $funcCall;
}

// skip (string) ternary conditions with both values
if ($this->isStringCastedTernaryOfMixedTypes($argValue, $scope)) {
return null;
}

if ($this->shouldSkipValue($argValue, $scope, $isTrait, $targetType)) {
return null;
}
Expand All @@ -72,6 +79,7 @@ public function convertIfNull(
}

if ($argValue instanceof Ternary && ! $this->shouldSkipValue($argValue->else, $scope, $isTrait, $targetType)) {

if ($this->valueResolver->isNull($argValue->else)) {
$argValue->else = $targetType === 'string' ? new String_('') : new Int_(0);
} else {
Expand All @@ -81,12 +89,27 @@ public function convertIfNull(
}

$args[$position]->value = $argValue;
$funcCall->args = $args;

return $funcCall;
}

$args[$position]->value = $targetType === 'string' ? new CastString_($argValue) : new CastInt_($argValue);
$funcCall->args = $args;
$wrapInParentheses = false;
if ($argValue instanceof Ternary && $argValue->cond instanceof CastString_) {
$wrapInParentheses = true;
}

if ($targetType === 'string') {
$castedType = new CastString_($argValue);
} else {
$castedType = new CastInt_($argValue);
}

if ($wrapInParentheses) {
$argValue->setAttribute(AttributeKey::WRAPPED_IN_PARENTHESES, true);
}

$args[$position]->value = $castedType;

return $funcCall;
}

Expand Down Expand Up @@ -221,4 +244,23 @@ private function isPossibleArrayVariableName(Type $passedType, Type $reflectionP

return false;
}

private function isStringCastedTernaryOfMixedTypes(Expr $expr, Scope $scope): bool
{
if (! $expr instanceof Ternary) {
return false;
}

if (! $expr->cond instanceof CastString_) {
return false;
}

if (! $expr->if instanceof Expr) {
return false;
}

$ifType = $scope->getType($expr->if);
$elseType = $scope->getType($expr->else);
return $ifType instanceof MixedType || $elseType instanceof MixedType;
}
}