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