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\AutowiredService;
9: use PHPStan\DependencyInjection\Container;
10: use PHPStan\Reflection\ReflectionProvider;
11: use PHPStan\Rules\Rule;
12: use PHPStan\Rules\RuleErrorBuilder;
13:
14: /**
15: * @implements Rule<Node\Expr\FuncCall>
16: */
17: #[AutowiredService]
18: final class RestrictedFunctionUsageRule implements Rule
19: {
20:
21: public function __construct(
22: private Container $container,
23: private ReflectionProvider $reflectionProvider,
24: )
25: {
26: }
27:
28: public function getNodeType(): string
29: {
30: return Node\Expr\FuncCall::class;
31: }
32:
33: /**
34: * @api
35: */
36: public function processNode(Node $node, Scope $scope): array
37: {
38: if (!($node->name instanceof Name)) {
39: return [];
40: }
41:
42: if (!$this->reflectionProvider->hasFunction($node->name, $scope)) {
43: return [];
44: }
45:
46: $functionReflection = $this->reflectionProvider->getFunction($node->name, $scope);
47:
48: /** @var RestrictedFunctionUsageExtension[] $extensions */
49: $extensions = $this->container->getServicesByTag(RestrictedFunctionUsageExtension::FUNCTION_EXTENSION_TAG);
50: $errors = [];
51:
52: foreach ($extensions as $extension) {
53: $restrictedUsage = $extension->isRestrictedFunctionUsage($functionReflection, $scope);
54: if ($restrictedUsage === null) {
55: continue;
56: }
57:
58: $errors[] = RuleErrorBuilder::message($restrictedUsage->errorMessage)
59: ->identifier($restrictedUsage->identifier)
60: ->build();
61: }
62:
63: return $errors;
64: }
65:
66: }
67: