Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit e37b23f

Browse files
committed
Add ReadWritePropertiesExtension for Gedmo annotations/attributes
1 parent c5ec462 commit e37b23f

File tree

8 files changed

+231
-2
lines changed

8 files changed

+231
-2
lines changed

‎composer.json‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
],
88
"require": {
99
"php": "^7.2 || ^8.0",
10-
"phpstan/phpstan": "^1.8.0"
10+
"phpstan/phpstan": "^1.8.0",
11+
"doctrine/annotations": "^1.11.0"
1112
},
1213
"conflict": {
1314
"doctrine/collections": "<1.0",
@@ -17,14 +18,14 @@
1718
"doctrine/persistence": "<1.3"
1819
},
1920
"require-dev": {
20-
"doctrine/annotations": "^1.11.0",
2121
"doctrine/collections": "^1.6",
2222
"doctrine/common": "^2.7 || ^3.0",
2323
"doctrine/dbal": "^2.13.8 || ^3.3.3",
2424
"doctrine/lexer": "^1.2.1",
2525
"doctrine/mongodb-odm": "^1.3 || ^2.1",
2626
"doctrine/orm": "^2.11.0",
2727
"doctrine/persistence": "^1.3.8 || ^2.2.1",
28+
"gedmo/doctrine-extensions": "^3.8",
2829
"nesbot/carbon": "^2.49",
2930
"nikic/php-parser": "^4.13.2",
3031
"php-parallel-lint/php-parallel-lint": "^1.2",

‎extension.neon‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,3 +371,8 @@ services:
371371
class: PHPStan\Type\Doctrine\Collection\IsEmptyTypeSpecifyingExtension
372372
tags:
373373
- phpstan.typeSpecifier.methodTypeSpecifyingExtension
374+
375+
-
376+
class: PHPStan\Rules\Gedmo\PropertiesExtension
377+
tags:
378+
- phpstan.properties.readWriteExtension

‎phpstan-baseline.neon‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ parameters:
55
count: 1
66
path: src/Doctrine/Mapping/ClassMetadataFactory.php
77

8+
-
9+
message: "#^Call to method getProperty\(\) on an unknown class PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionEnum\.$#"
10+
count: 1
11+
path: src/Rules/Gedmo/PropertiesExtension.php
12+
813
-
914
message: "#^Accessing PHPStan\\\\Rules\\\\DeadCode\\\\UnusedPrivatePropertyRule\\:\\:class is not covered by backward compatibility promise\\. The class might change in a minor PHPStan version\\.$#"
1015
count: 1
@@ -20,6 +25,16 @@ parameters:
2025
count: 1
2126
path: tests/Rules/Exceptions/CatchWithUnthrownExceptionRuleTest.php
2227

28+
-
29+
message: "#^Accessing PHPStan\\\\Rules\\\\DeadCode\\\\UnusedPrivatePropertyRule\\:\\:class is not covered by backward compatibility promise\\. The class might change in a minor PHPStan version\\.$#"
30+
count: 1
31+
path: tests/Rules/Properties/MissingGedmoByPhpDocPropertyAssignRuleTest.php
32+
33+
-
34+
message: "#^Accessing PHPStan\\\\Rules\\\\DeadCode\\\\UnusedPrivatePropertyRule\\:\\:class is not covered by backward compatibility promise\\. The class might change in a minor PHPStan version\\.$#"
35+
count: 1
36+
path: tests/Rules/Properties/MissingGedmoPropertyAssignRuleTest.php
37+
2338
-
2439
message: "#^Accessing PHPStan\\\\Rules\\\\Properties\\\\MissingReadOnlyByPhpDocPropertyAssignRule\\:\\:class is not covered by backward compatibility promise\\. The class might change in a minor PHPStan version\\.$#"
2540
count: 1
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Gedmo;
4+
5+
use Doctrine\Common\Annotations\AnnotationReader;
6+
use Gedmo\Mapping\Annotation as Gedmo;
7+
use PHPStan\Reflection\PropertyReflection;
8+
use PHPStan\Rules\Properties\ReadWritePropertiesExtension;
9+
use function get_class;
10+
use function in_array;
11+
12+
class PropertiesExtension implements ReadWritePropertiesExtension
13+
{
14+
15+
private const GEDMO_WRITE_CLASSLIST = [
16+
Gedmo\Blameable::class,
17+
Gedmo\IpTraceable::class,
18+
Gedmo\Locale::class,
19+
Gedmo\Language::class,
20+
Gedmo\Slug::class,
21+
Gedmo\SortablePosition::class,
22+
Gedmo\Timestampable::class,
23+
Gedmo\TreeLeft::class,
24+
Gedmo\TreeLevel::class,
25+
Gedmo\TreeParent::class,
26+
Gedmo\TreePath::class,
27+
Gedmo\TreePathHash::class,
28+
Gedmo\TreeRight::class,
29+
Gedmo\TreeRoot::class,
30+
Gedmo\UploadableFileMimeType::class,
31+
Gedmo\UploadableFileName::class,
32+
Gedmo\UploadableFilePath::class,
33+
Gedmo\UploadableFileSize::class,
34+
];
35+
36+
private const GEDMO_READ_CLASSLIST = [
37+
Gedmo\Locale::class,
38+
Gedmo\Language::class,
39+
];
40+
41+
/** @var AnnotationReader */
42+
private $annotationReader;
43+
44+
public function __construct()
45+
{
46+
$this->annotationReader = new AnnotationReader();
47+
}
48+
49+
public function isAlwaysRead(PropertyReflection $property, string $propertyName): bool
50+
{
51+
return $this->isGedmoAnnotationOrAttribute($property, $propertyName, self::GEDMO_READ_CLASSLIST);
52+
}
53+
54+
public function isAlwaysWritten(PropertyReflection $property, string $propertyName): bool
55+
{
56+
return $this->isGedmoAnnotationOrAttribute($property, $propertyName, self::GEDMO_WRITE_CLASSLIST);
57+
}
58+
59+
public function isInitialized(PropertyReflection $property, string $propertyName): bool
60+
{
61+
return false;
62+
}
63+
64+
/**
65+
* @param array<class-string> $classList
66+
*/
67+
private function isGedmoAnnotationOrAttribute(PropertyReflection $property, string $propertyName, array $classList): bool
68+
{
69+
$propertyReflection = $property->getDeclaringClass()->getNativeReflection()->getProperty($propertyName);
70+
71+
$annotations = $this->annotationReader->getPropertyAnnotations($propertyReflection);
72+
foreach ($annotations as $annotation) {
73+
if (in_array(get_class($annotation), $classList, true)) {
74+
return true;
75+
}
76+
}
77+
78+
$attributes = $propertyReflection->getAttributes();
79+
foreach ($attributes as $attribute) {
80+
if (in_array($attribute->getName(), $classList, true)) {
81+
return true;
82+
}
83+
}
84+
85+
return false;
86+
}
87+
88+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Properties;
4+
5+
use PHPStan\Rules\DeadCode\UnusedPrivatePropertyRule;
6+
use PHPStan\Rules\Gedmo\PropertiesExtension;
7+
use PHPStan\Rules\Rule;
8+
use PHPStan\Testing\RuleTestCase;
9+
use const PHP_VERSION_ID;
10+
11+
/**
12+
* @extends RuleTestCase<UnusedPrivatePropertyRule>
13+
*/
14+
class MissingGedmoByPhpDocPropertyAssignRuleTest extends RuleTestCase
15+
{
16+
17+
protected function getRule(): Rule
18+
{
19+
return self::getContainer()->getByType(UnusedPrivatePropertyRule::class);
20+
}
21+
22+
protected function getReadWritePropertiesExtensions(): array
23+
{
24+
return [
25+
new PropertiesExtension(),
26+
];
27+
}
28+
29+
public static function getAdditionalConfigFiles(): array
30+
{
31+
return [__DIR__ . '/../../../extension.neon'];
32+
}
33+
34+
public function testRule(): void
35+
{
36+
if (PHP_VERSION_ID < 70400) {
37+
self::markTestSkipped('Test requires PHP 7.4.');
38+
}
39+
40+
$this->analyse([__DIR__ . '/data/gedmo-property-assign.php'], [
41+
// No errors expected
42+
]);
43+
}
44+
45+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Properties;
4+
5+
use PHPStan\Rules\DeadCode\UnusedPrivatePropertyRule;
6+
use PHPStan\Rules\Gedmo\PropertiesExtension;
7+
use PHPStan\Rules\Rule;
8+
use PHPStan\Testing\RuleTestCase;
9+
use const PHP_VERSION_ID;
10+
11+
/**
12+
* @extends RuleTestCase<UnusedPrivatePropertyRule>
13+
*/
14+
class MissingGedmoPropertyAssignRuleTest extends RuleTestCase
15+
{
16+
17+
protected function getRule(): Rule
18+
{
19+
return self::getContainer()->getByType(UnusedPrivatePropertyRule::class);
20+
}
21+
22+
protected function getReadWritePropertiesExtensions(): array
23+
{
24+
return [
25+
new PropertiesExtension(),
26+
];
27+
}
28+
29+
public static function getAdditionalConfigFiles(): array
30+
{
31+
return [__DIR__ . '/../../../extension.neon'];
32+
}
33+
34+
public function testRule(): void
35+
{
36+
if (PHP_VERSION_ID < 80100) {
37+
self::markTestSkipped('Test requires PHP 8.1.');
38+
}
39+
40+
$this->analyse([__DIR__ . '/data/gedmo-property-assign.php'], [
41+
// No errors expected
42+
]);
43+
}
44+
45+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php // lint >= 7.4
2+
3+
namespace MissingGedmoWrittenPropertyAssignPhpDoc;
4+
5+
use Doctrine\ORM\Mapping as ORM;
6+
use Gedmo\Mapping\Annotation as Gedmo;
7+
8+
/**
9+
* @ORM\Entity
10+
*/
11+
class EntityWithAGemdoLocaleField
12+
{
13+
/**
14+
* @Gedmo\Locale
15+
*/
16+
private string $locale; // ok, locale is written and read by gedmo listeners
17+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php // lint >= 8.1
2+
3+
namespace MissingGedmoWrittenPropertyAssign;
4+
5+
use Doctrine\ORM\Mapping as ORM;
6+
use Gedmo\Mapping\Annotation as Gedmo;
7+
8+
#[ORM\Entity]
9+
class EntityWithAGemdoLocaleField
10+
{
11+
#[Gedmo\Locale]
12+
private string $locale; // ok, locale is written and read by gedmo listeners
13+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /