2424use PHPStan \Type \Type ;
2525use PHPStan \Type \UnionType ;
2626use Rector \NodeAnalyzer \PropertyFetchAnalyzer ;
27+ use Rector \NodeTypeResolver \Node \AttributeKey ;
2728use Rector \NodeTypeResolver \NodeTypeResolver ;
2829use Rector \PhpParser \Node \Value \ValueResolver ;
2930
@@ -53,12 +54,18 @@ public function convertIfNull(
5354 }
5455
5556 $ argValue = $ args [$ position ]->value ;
57+
5658 if ($ this ->valueResolver ->isNull ($ argValue )) {
5759 $ args [$ position ]->value = $ targetType === 'string ' ? new String_ ('' ) : new Int_ (0 );
5860 $ funcCall ->args = $ args ;
5961 return $ funcCall ;
6062 }
6163
64+ // skip (string) ternary conditions with both values
65+ if ($ this ->isStringCastedTernaryOfMixedTypes ($ argValue , $ scope )) {
66+ return null ;
67+ }
68+
6269 if ($ this ->shouldSkipValue ($ argValue , $ scope , $ isTrait , $ targetType )) {
6370 return null ;
6471 }
@@ -72,6 +79,7 @@ public function convertIfNull(
7279 }
7380
7481 if ($ argValue instanceof Ternary && ! $ this ->shouldSkipValue ($ argValue ->else , $ scope , $ isTrait , $ targetType )) {
82+
7583 if ($ this ->valueResolver ->isNull ($ argValue ->else )) {
7684 $ argValue ->else = $ targetType === 'string ' ? new String_ ('' ) : new Int_ (0 );
7785 } else {
@@ -81,12 +89,27 @@ public function convertIfNull(
8189 }
8290
8391 $ args [$ position ]->value = $ argValue ;
84- $ funcCall -> args = $ args ;
92+
8593 return $ funcCall ;
8694 }
8795
88- $ args [$ position ]->value = $ targetType === 'string ' ? new CastString_ ($ argValue ) : new CastInt_ ($ argValue );
89- $ funcCall ->args = $ args ;
96+ $ wrapInParentheses = false ;
97+ if ($ argValue instanceof Ternary && $ argValue ->cond instanceof CastString_) {
98+ $ wrapInParentheses = true ;
99+ }
100+
101+ if ($ targetType === 'string ' ) {
102+ $ castedType = new CastString_ ($ argValue );
103+ } else {
104+ $ castedType = new CastInt_ ($ argValue );
105+ }
106+
107+ if ($ wrapInParentheses ) {
108+ $ argValue ->setAttribute (AttributeKey::WRAPPED_IN_PARENTHESES , true );
109+ }
110+
111+ $ args [$ position ]->value = $ castedType ;
112+
90113 return $ funcCall ;
91114 }
92115
@@ -221,4 +244,23 @@ private function isPossibleArrayVariableName(Type $passedType, Type $reflectionP
221244
222245 return false ;
223246 }
247+
248+ private function isStringCastedTernaryOfMixedTypes (Expr $ expr , Scope $ scope ): bool
249+ {
250+ if (! $ expr instanceof Ternary) {
251+ return false ;
252+ }
253+
254+ if (! $ expr ->cond instanceof CastString_) {
255+ return false ;
256+ }
257+
258+ if (! $ expr ->if instanceof Expr) {
259+ return false ;
260+ }
261+
262+ $ ifType = $ scope ->getType ($ expr ->if );
263+ $ elseType = $ scope ->getType ($ expr ->else );
264+ return $ ifType instanceof MixedType || $ elseType instanceof MixedType;
265+ }
224266}
0 commit comments