1212use PhpParser \Node \Expr \FuncCall ;
1313use PHPStan \Analyser \Scope ;
1414use PHPStan \Reflection \FunctionReflection ;
15- use PHPStan \Reflection \ParametersAcceptorSelector ;
16- use PHPStan \Type \Type ;
1715use PHPStan \Type \ArrayType ;
18- use PHPStan \Type \StringType ;
16+ use PHPStan \Type \Constant \ ConstantStringType ;
1917use PHPStan \Type \IntegerType ;
2018use PHPStan \Type \MixedType ;
21- use PHPStan \Type \ObjectType ;
2219use PHPStan \Type \NullType ;
20+ use PHPStan \Type \ObjectType ;
21+ use PHPStan \Type \StringType ;
22+ use PHPStan \Type \Type ;
2323use PHPStan \Type \TypeCombinator ;
24- use PHPStan \Type \Constant \ConstantStringType ;
2524
2625class GetPostDynamicFunctionReturnTypeExtension implements \PHPStan \Type \DynamicFunctionReturnTypeExtension
2726{
@@ -30,35 +29,76 @@ public function isFunctionSupported(FunctionReflection $functionReflection): boo
3029 return in_array ($ functionReflection ->getName (), ['get_post ' , 'get_page_by_path ' ], true );
3130 }
3231
33- // phpcs:ignore SlevomatCodingStandard.Functions.UnusedParameter
32+ /**
33+ * @see https://developer.wordpress.org/reference/functions/get_post/
34+ * @see https://developer.wordpress.org/reference/functions/get_page_by_path/
35+ */
3436 public function getTypeFromFunctionCall (FunctionReflection $ functionReflection , FuncCall $ functionCall , Scope $ scope ): Type
3537 {
3638 $ output = 'OBJECT ' ;
3739 $ args = $ functionCall ->getArgs ();
3840
39- if (count ($ functionCall ->args ) >= 2 ) {
40- $ argumentType = $ scope ->getType ($ args [1 ]->value );
41-
41+ $ returnType = self ::objectType ();
42+ if (count ($ args ) >= 2 ) {
4243 // When called with an $output that isn't a constant string, return default return type
43- if (! $ argumentType instanceof ConstantStringType) {
44- return ParametersAcceptorSelector::selectFromArgs (
45- $ scope ,
46- $ args ,
47- $ functionReflection ->getVariants ()
48- )->getReturnType ();
44+ if (! $ scope ->getType ($ args [1 ]->value ) instanceof ConstantStringType) {
45+ $ returnType = self ::defaultType ();
46+ }
47+ if ($ args [1 ]->value instanceof ConstFetch) {
48+ $ output = $ args [1 ]->value ->name ->getLast ();
49+ switch ($ output ) {
50+ case 'ARRAY_A ' :
51+ $ returnType = self ::associativeArrayType ();
52+ break ;
53+ case 'ARRAY_N ' :
54+ $ returnType = self ::numericArrayType ();
55+ break ;
56+ }
4957 }
5058 }
5159
52- if (count ($ args ) >= 2 && $ args [1 ]->value instanceof ConstFetch) {
53- $ output = $ args [1 ]->value ->name ->getLast ();
54- }
55- if ($ output === 'ARRAY_A ' ) {
56- return TypeCombinator::union (new ArrayType (new StringType (), new MixedType ()), new NullType ());
60+ if ($ functionReflection ->getName () !== 'get_post ' ) {
61+ return $ returnType ;
5762 }
58- if ($ output === 'ARRAY_N ' ) {
59- return TypeCombinator::union (new ArrayType (new IntegerType (), new MixedType ()), new NullType ());
63+
64+ $ firstArgType = count ($ args ) > 0 ? $ scope ->getType ($ args [0 ]->value ) : new NullType ();
65+ if ($ firstArgType instanceof ObjectType && $ firstArgType ->isInstanceOf ('WP_Post ' )->yes ()) {
66+ $ returnType = TypeCombinator::remove ($ returnType , new NullType ());
6067 }
6168
62- return TypeCombinator::union (new ObjectType ('WP_Post ' ), new NullType ());
69+ return $ returnType ;
70+ }
71+
72+ protected static function objectType (): Type
73+ {
74+ return TypeCombinator::union (
75+ new ObjectType ('WP_Post ' ),
76+ new NullType ()
77+ );
78+ }
79+
80+ protected static function associativeArrayType (): Type
81+ {
82+ return TypeCombinator::union (
83+ new ArrayType (new StringType (), new MixedType ()),
84+ new NullType ()
85+ );
86+ }
87+
88+ protected static function numericArrayType (): Type
89+ {
90+ return TypeCombinator::union (
91+ new ArrayType (new IntegerType (), new MixedType ()),
92+ new NullType ()
93+ );
94+ }
95+
96+ protected static function defaultType (): Type
97+ {
98+ return TypeCombinator::union (
99+ self ::objectType (),
100+ self ::associativeArrayType (),
101+ self ::numericArrayType ()
102+ );
63103 }
64104}
0 commit comments