Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit fc8e374

Browse files
committed
[PropertyInfo] restrict access to PhpStanExtractor based on visibility
1 parent 82e0eff commit fc8e374

File tree

4 files changed

+64
-3
lines changed

4 files changed

+64
-3
lines changed

src/Symfony/Component/PropertyInfo/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ CHANGELOG
55
---
66

77
* Introduce `PropertyDocBlockExtractorInterface` to extract a property's doc block
8+
* Restrict access to `PhpStanExtractor` based on visibility
89

910
6.4
1011
---

src/Symfony/Component/PropertyInfo/Extractor/PhpStanExtractor.php

+17-3
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,14 @@ final class PhpStanExtractor implements PropertyTypeExtractorInterface, Construc
4747
private array $mutatorPrefixes;
4848
private array $accessorPrefixes;
4949
private array $arrayMutatorPrefixes;
50+
private bool $allowPrivateAccess;
5051

5152
/**
5253
* @param list<string>|null $mutatorPrefixes
5354
* @param list<string>|null $accessorPrefixes
5455
* @param list<string>|null $arrayMutatorPrefixes
5556
*/
56-
public function __construct(array $mutatorPrefixes = null, array $accessorPrefixes = null, array $arrayMutatorPrefixes = null)
57+
public function __construct(array $mutatorPrefixes = null, array $accessorPrefixes = null, array $arrayMutatorPrefixes = null, bool $allowPrivateAccess = true)
5758
{
5859
if (!class_exists(ContextFactory::class)) {
5960
throw new \LogicException(sprintf('Unable to use the "%s" class as the "phpdocumentor/type-resolver" package is not installed. Try running composer require "phpdocumentor/type-resolver".', __CLASS__));
@@ -67,6 +68,7 @@ public function __construct(array $mutatorPrefixes = null, array $accessorPrefix
6768
$this->mutatorPrefixes = $mutatorPrefixes ?? ReflectionExtractor::$defaultMutatorPrefixes;
6869
$this->accessorPrefixes = $accessorPrefixes ?? ReflectionExtractor::$defaultAccessorPrefixes;
6970
$this->arrayMutatorPrefixes = $arrayMutatorPrefixes ?? ReflectionExtractor::$defaultArrayMutatorPrefixes;
71+
$this->allowPrivateAccess = $allowPrivateAccess;
7072

7173
$this->phpDocParser = new PhpDocParser(new TypeParser(new ConstExprParser()), new ConstExprParser());
7274
$this->lexer = new Lexer();
@@ -232,6 +234,10 @@ private function getDocBlockFromProperty(string $class, string $property): ?arra
232234
return null;
233235
}
234236

237+
if (!$this->canAccessMemberBasedOnItsVisibility($reflectionProperty)) {
238+
return null;
239+
}
240+
235241
// Type can be inside property docblock as `@var`
236242
$rawDocNode = $reflectionProperty->getDocComment();
237243
$phpDocNode = $rawDocNode ? $this->getPhpDocNode($rawDocNode) : null;
@@ -274,8 +280,11 @@ private function getDocBlockFromMethod(string $class, string $ucFirstProperty, i
274280
}
275281

276282
if (
277-
(self::ACCESSOR === $type && 0 === $reflectionMethod->getNumberOfRequiredParameters())
278-
|| (self::MUTATOR === $type && $reflectionMethod->getNumberOfParameters() >= 1)
283+
$this->canAccessMemberBasedOnItsVisibility($reflectionMethod)
284+
&& (
285+
(self::ACCESSOR === $type && 0 === $reflectionMethod->getNumberOfRequiredParameters())
286+
|| (self::MUTATOR === $type && $reflectionMethod->getNumberOfParameters() >= 1)
287+
)
279288
) {
280289
break;
281290
}
@@ -305,4 +314,9 @@ private function getPhpDocNode(string $rawDocNode): PhpDocNode
305314

306315
return $phpDocNode;
307316
}
317+
318+
public function canAccessMemberBasedOnItsVisibility(\ReflectionProperty|\ReflectionMethod $member): bool
319+
{
320+
return $member->isPublic() || $this->allowPrivateAccess;
321+
}
308322
}

src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpStanExtractorTest.php

+21
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Symfony\Component\PropertyInfo\Tests\Fixtures\ConstructorDummyWithoutDocBlock;
1818
use Symfony\Component\PropertyInfo\Tests\Fixtures\DefaultValue;
1919
use Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy;
20+
use Symfony\Component\PropertyInfo\Tests\Fixtures\DummyPropertyAndGetterWithDifferentTypes;
2021
use Symfony\Component\PropertyInfo\Tests\Fixtures\ParentDummy;
2122
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php80Dummy;
2223
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php80PromotedDummy;
@@ -475,6 +476,26 @@ public static function php80TypesProvider()
475476
[Php80PromotedDummy::class, 'promoted', null],
476477
];
477478
}
479+
480+
public static function allowPrivateAccessProvider(): array
481+
{
482+
return [
483+
[true, [new Type(Type::BUILTIN_TYPE_STRING)]],
484+
[false, [new Type(Type::BUILTIN_TYPE_ARRAY, collection: true, collectionKeyType: new Type('int'), collectionValueType: new Type('string'))]],
485+
];
486+
}
487+
488+
/**
489+
* @dataProvider allowPrivateAccessProvider
490+
*/
491+
public function testAllowPrivateAccess(bool $allowPrivateAccess, array $expectedTypes)
492+
{
493+
$extractor = new PhpStanExtractor(allowPrivateAccess: $allowPrivateAccess);
494+
$this->assertEquals(
495+
$expectedTypes,
496+
$extractor->getTypes(DummyPropertyAndGetterWithDifferentTypes::class, 'foo')
497+
);
498+
}
478499
}
479500

480501
class PhpStanOmittedParamTagTypeDocBlock
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Symfony\Component\PropertyInfo\Tests\Fixtures;
6+
7+
final readonly class DummyPropertyAndGetterWithDifferentTypes
8+
{
9+
public function __construct(
10+
/**
11+
* @var string
12+
*/
13+
private string $foo
14+
)
15+
{
16+
}
17+
18+
/**
19+
* @return array<int, string>
20+
*/
21+
public function getFoo(): array
22+
{
23+
return (array) $this->foo;
24+
}
25+
}

0 commit comments

Comments
 (0)