1: <?php declare(strict_types = 1);
2:
3: namespace PHPStan\Rules\RestrictedUsage;
4:
5: use PhpParser\Node;
6: use PhpParser\Node\Name;
7: use PHPStan\Analyser\Scope;
8: use PHPStan\DependencyInjection\AutowiredExtensions;
9: use PHPStan\DependencyInjection\AutowiredService;
10: use PHPStan\DependencyInjection\ExtensionsCollection;
11: use PHPStan\Node\FunctionCallableNode;
12: use PHPStan\Reflection\ReflectionProvider;
13: use PHPStan\Rules\Rule;
14: use PHPStan\Rules\RuleErrorBuilder;
15:
16: /**
17: * @implements Rule<FunctionCallableNode>
18: */
19: #[AutowiredService]
20: final class RestrictedFunctionCallableUsageRule implements Rule
21: {
22:
23: /**
24: * @param ExtensionsCollection<RestrictedFunctionUsageExtension> $extensions
25: */
26: public function __construct(
27: #[AutowiredExtensions(of: RestrictedFunctionUsageExtension::class)]
28: private ExtensionsCollection $extensions,
29: private ReflectionProvider $reflectionProvider,
30: )
31: {
32: }
33:
34: public function getNodeType(): string
35: {
36: return FunctionCallableNode::class;
37: }
38:
39: /**
40: * @api
41: */
42: public function processNode(Node $node, Scope $scope): array
43: {
44: if (!($node->getName() instanceof Name)) {
45: return [];
46: }
47:
48: if (!$this->reflectionProvider->hasFunction($node->getName(), $scope)) {
49: return [];
50: }
51:
52: $functionReflection = $this->reflectionProvider->getFunction($node->getName(), $scope);
53:
54: $extensions = $this->extensions->getAll();
55: $errors = [];
56:
57: foreach ($extensions as $extension) {
58: $restrictedUsage = $extension->isRestrictedFunctionUsage($functionReflection, $scope);
59: if ($restrictedUsage === null) {
60: continue;
61: }
62:
63: $errors[] = RuleErrorBuilder::message($restrictedUsage->errorMessage)
64: ->identifier($restrictedUsage->identifier)
65: ->build();
66: }
67:
68: return $errors;
69: }
70:
71: }
72: