Skip to content

Commit c7fd1ac

Browse files
Add a dynamic return type extension for current_time() (#60)
Co-authored-by: Viktor Szépe <viktor@szepe.net>
1 parent d5e6263 commit c7fd1ac

File tree

4 files changed

+83
-0
lines changed

4 files changed

+83
-0
lines changed

extension.neon

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ services:
4343
class: SzepeViktor\PHPStan\WordPress\MySQL2DateDynamicFunctionReturnTypeExtension
4444
tags:
4545
- phpstan.broker.dynamicFunctionReturnTypeExtension
46+
-
47+
class: SzepeViktor\PHPStan\WordPress\CurrentTimeDynamicFunctionReturnTypeExtension
48+
tags:
49+
- phpstan.broker.dynamicFunctionReturnTypeExtension
4650
parameters:
4751
bootstrapFiles:
4852
- %rootDir%/../../php-stubs/wordpress-stubs/wordpress-stubs.php
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
/**
4+
* Set return type of current_time().
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace SzepeViktor\PHPStan\WordPress;
10+
11+
use PhpParser\Node\Expr\FuncCall;
12+
use PHPStan\Analyser\Scope;
13+
use PHPStan\Reflection\FunctionReflection;
14+
use PHPStan\Reflection\ParametersAcceptorSelector;
15+
use PHPStan\Type\Type;
16+
use PHPStan\Type\IntegerType;
17+
use PHPStan\Type\StringType;
18+
use PHPStan\Type\Constant\ConstantStringType;
19+
20+
class CurrentTimeDynamicFunctionReturnTypeExtension implements \PHPStan\Type\DynamicFunctionReturnTypeExtension
21+
{
22+
public function isFunctionSupported(FunctionReflection $functionReflection): bool
23+
{
24+
return in_array($functionReflection->getName(), ['current_time'], true);
25+
}
26+
27+
/**
28+
* @see https://developer.wordpress.org/reference/functions/current_time/
29+
*/
30+
public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): Type
31+
{
32+
$argumentType = $scope->getType($functionCall->args[0]->value);
33+
34+
// When called with a $type that isn't a constant string, return default return type
35+
if (! $argumentType instanceof ConstantStringType) {
36+
return ParametersAcceptorSelector::selectFromArgs(
37+
$scope,
38+
$functionCall->args,
39+
$functionReflection->getVariants()
40+
)->getReturnType();
41+
}
42+
43+
// Called with a constant string $type
44+
switch ($argumentType->getValue()) {
45+
case 'timestamp':
46+
case 'U':
47+
return new IntegerType();
48+
case 'mysql':
49+
default:
50+
return new StringType();
51+
}
52+
}
53+
}

tests/data/current_time.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SzepeViktor\PHPStan\WordPress\Tests;
6+
7+
use function current_time;
8+
use function PHPStan\Testing\assertType;
9+
use stdClass;
10+
11+
// Integer types
12+
assertType('int', current_time('timestamp'));
13+
assertType('int', current_time('U'));
14+
15+
// String types
16+
assertType('string', current_time('mysql'));
17+
assertType('string', current_time('Hello'));
18+
19+
// Unknown types
20+
assertType('int|string', current_time($_GET['foo']));
21+
assertType('int|string', current_time(get_option('date_format')));
22+
23+
// Unsupported types
24+
assertType('int|string', current_time(new stdClass));
25+
assertType('int|string', current_time(false));

tests/testTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ class DynamicReturnTypeExtensionTests extends TypeInferenceTestCase
1515
public function dataFileAsserts(): iterable
1616
{
1717
// path to a file with actual asserts of expected types:
18+
yield from $this->gatherAssertTypes(__DIR__ . '/data/current_time.php');
1819
yield from $this->gatherAssertTypes(__DIR__ . '/data/get_comment.php');
1920
yield from $this->gatherAssertTypes(__DIR__ . '/data/get_object_taxonomies.php');
2021
yield from $this->gatherAssertTypes(__DIR__ . '/data/mysql2date.php');

0 commit comments

Comments
 (0)