Skip to content

Commit d116f74

Browse files
Merge pull request #131 from alexanderschnitzler/feature/add-datetimeaspect-get-dynamic-return-type-extension
[FEATURE] Add dynamic return type extension for DateTimeAspect::get()
2 parents 4bb2c58 + 85a7549 commit d116f74

File tree

4 files changed

+126
-0
lines changed

4 files changed

+126
-0
lines changed

extension.neon

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ services:
101101
class: SaschaEgerer\PhpstanTypo3\Type\UserAspectGetDynamicReturnTypeExtension
102102
tags:
103103
- phpstan.broker.dynamicMethodReturnTypeExtension
104+
-
105+
class: SaschaEgerer\PhpstanTypo3\Type\DateTimeAspectGetDynamicReturnTypeExtension
106+
tags:
107+
- phpstan.broker.dynamicMethodReturnTypeExtension
104108
parameters:
105109
bootstrapFiles:
106110
- phpstan.bootstrap.php
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace SaschaEgerer\PhpstanTypo3\Type;
4+
5+
use PhpParser\Node\Arg;
6+
use PhpParser\Node\Expr\MethodCall;
7+
use PHPStan\Analyser\Scope;
8+
use PHPStan\Reflection\MethodReflection;
9+
use PHPStan\Type\Constant\ConstantStringType;
10+
use PHPStan\Type\DynamicMethodReturnTypeExtension;
11+
use PHPStan\Type\IntegerType;
12+
use PHPStan\Type\ObjectType;
13+
use PHPStan\Type\StringType;
14+
use TYPO3\CMS\Core\Context\DateTimeAspect;
15+
16+
class DateTimeAspectGetDynamicReturnTypeExtension implements DynamicMethodReturnTypeExtension
17+
{
18+
19+
public function getClass(): string
20+
{
21+
return DateTimeAspect::class;
22+
}
23+
24+
public function isMethodSupported(MethodReflection $methodReflection): bool
25+
{
26+
return $methodReflection->getName() === 'get';
27+
}
28+
29+
public function getTypeFromMethodCall(
30+
MethodReflection $methodReflection,
31+
MethodCall $methodCall,
32+
Scope $scope
33+
): ?\PHPStan\Type\Type
34+
{
35+
$firstArgument = $methodCall->args[0];
36+
37+
if (!$firstArgument instanceof Arg) {
38+
return null;
39+
}
40+
41+
$argumentType = $scope->getType($firstArgument->value);
42+
43+
if ($argumentType instanceof ConstantStringType) {
44+
switch ($argumentType->getValue()) {
45+
case 'timestamp':
46+
case 'accessTime':
47+
return new IntegerType();
48+
case 'iso':
49+
case 'timezone':
50+
return new StringType();
51+
case 'full':
52+
return new ObjectType(\DateTimeImmutable::class);
53+
}
54+
}
55+
56+
return null;
57+
}
58+
59+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace SaschaEgerer\PhpstanTypo3\Tests\Unit\Type\DateTimeAspectGetDynamicReturnTypeExtension;
4+
5+
use PHPStan\Testing\TypeInferenceTestCase;
6+
7+
final class DateTimeAspectGetDynamicReturnTypeExtensionTest extends TypeInferenceTestCase
8+
{
9+
10+
/**
11+
*
12+
* @return iterable<mixed>
13+
*/
14+
public function dataFileAsserts(): iterable
15+
{
16+
yield from $this->gatherAssertTypes(__DIR__ . '/data/datetime-aspect-get-return-types.php');
17+
}
18+
19+
/**
20+
* @dataProvider dataFileAsserts
21+
* @param string $assertType
22+
* @param string $file
23+
* @param mixed ...$args
24+
*/
25+
public function testFileAsserts(
26+
string $assertType,
27+
string $file,
28+
...$args
29+
): void
30+
{
31+
$this->assertFileAsserts($assertType, $file, ...$args);
32+
}
33+
34+
public static function getAdditionalConfigFiles(): array
35+
{
36+
return [
37+
__DIR__ . '/../../../../extension.neon',
38+
];
39+
}
40+
41+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace SaschaEgerer\PhpstanTypo3\Tests\Unit\Type\DateTimeAspectGetDynamicReturnTypeExtension\data;
4+
5+
use TYPO3\CMS\Core\Context\DateTimeAspect;
6+
7+
use function PHPStan\Testing\assertType;
8+
9+
// phpcs:ignore Squiz.Classes.ClassFileName.NoMatch
10+
class MyContext
11+
{
12+
13+
public function getTests(DateTimeAspect $context): void
14+
{
15+
assertType('int', $context->get('timestamp'));
16+
assertType('string', $context->get('iso'));
17+
assertType('string', $context->get('timezone'));
18+
assertType(\DateTimeImmutable::class, $context->get('full'));
19+
assertType('int', $context->get('accessTime'));
20+
}
21+
22+
}

0 commit comments

Comments
 (0)