Passed
Push — trunk ( 634730...0037c7 )
by Christian
13:42 queued 12s
created

NoDALAutoload::processNode()   C

Complexity

Conditions 14
Paths 34

Size

Total Lines 74
Code Lines 41

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 14
eloc 41
c 1
b 0
f 0
nc 34
nop 2
dl 0
loc 74
rs 6.2666

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php declare(strict_types=1);
2
3
namespace Shopware\Core\DevOps\StaticAnalyze\PHPStan\Rules;
4
5
use PhpParser\Node;
6
use PhpParser\Node\Expr\New_;
7
use PHPStan\Analyser\Scope;
0 ignored issues
show
Bug introduced by
The type PHPStan\Analyser\Scope was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
8
use PHPStan\Reflection\ReflectionProvider;
0 ignored issues
show
Bug introduced by
The type PHPStan\Reflection\ReflectionProvider was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
9
use PHPStan\Rules\Rule;
0 ignored issues
show
Bug introduced by
The type PHPStan\Rules\Rule was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
10
use PHPStan\Rules\RuleError;
0 ignored issues
show
Bug introduced by
The type PHPStan\Rules\RuleError was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
11
use PHPStan\Rules\RuleErrorBuilder;
0 ignored issues
show
Bug introduced by
The type PHPStan\Rules\RuleErrorBuilder was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
12
use PHPStan\Type\Constant\ConstantStringType;
0 ignored issues
show
Bug introduced by
The type PHPStan\Type\Constant\ConstantStringType was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
13
use Shopware\Core\Framework\DataAbstractionLayer\Field\ManyToOneAssociationField;
14
use Shopware\Core\Framework\DataAbstractionLayer\Field\OneToOneAssociationField;
15
use Shopware\Core\Framework\Log\Package;
16
17
/**
18
 * @implements Rule<New_>
19
 *
20
 * @internal
21
 */
22
#[Package('core')]
23
class NoDALAutoload implements Rule
24
{
25
    private const ASSOCIATIONS_WITH_AUTOLOAD = [
26
        OneToOneAssociationField::class,
27
        ManyToOneAssociationField::class,
28
    ];
29
30
    private ReflectionProvider $reflectionProvider;
31
32
    public function __construct(ReflectionProvider $reflectionProvider)
33
    {
34
        $this->reflectionProvider = $reflectionProvider;
35
    }
36
37
    public function getNodeType(): string
38
    {
39
        return New_::class;
40
    }
41
42
    /**
43
     * @param New_ $node
44
     *
45
     * @return array<array-key, RuleError|string>
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<array-key, RuleError|string> at position 2 could not be parsed: Unknown type name 'array-key' at position 2 in array<array-key, RuleError|string>.
Loading history...
46
     */
47
    public function processNode(Node $node, Scope $scope): array
48
    {
49
        if (!$scope->isInClass()) {
50
            return [];
51
        }
52
53
        $definitionClassReflection = $scope->getClassReflection()->getNativeReflection();
54
        $className = $definitionClassReflection->getName();
55
        if (str_contains($className, 'Test')) {
56
            //if in a test namespace, don't care
57
            return [];
58
        }
59
60
        if (!$node->class instanceof Node\Name) {
0 ignored issues
show
Bug introduced by
Accessing class on the interface PhpParser\Node suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
61
            return [];
62
        }
63
64
        if (!\in_array($node->class->toString(), self::ASSOCIATIONS_WITH_AUTOLOAD, true)) {
65
            return [];
66
        }
67
68
        $classReflection = $this->reflectionProvider
69
            ->getClass($node->class->toString())
70
            ->getNativeReflection();
71
72
        $construct = $classReflection->getMethod('__construct');
73
74
        $autoloadParamPosition = null;
75
        $propertyNameParamPosition = null;
76
        foreach ($construct->getParameters() as $param) {
77
            if ($param->name === 'autoload') {
78
                $autoloadParamPosition = $param->getPosition();
79
            }
80
81
            if ($param->name === 'propertyName') {
82
                $propertyNameParamPosition = $param->getPosition();
83
            }
84
        }
85
86
        if ($autoloadParamPosition === null || $propertyNameParamPosition === null) {
87
            //cannot find autoload or propertyName parameter
88
            return [];
89
        }
90
91
        if (!isset($node->getArgs()[$autoloadParamPosition])) {
0 ignored issues
show
Bug introduced by
The method getArgs() does not exist on PhpParser\Node. It seems like you code against a sub-type of PhpParser\Node such as PhpParser\Node\Expr\CallLike. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

91
        if (!isset($node->/** @scrutinizer ignore-call */ getArgs()[$autoloadParamPosition])) {
Loading history...
92
            //autoload parameter not passed
93
            return [];
94
        }
95
96
        $autoloadValueExpr = $node->getArgs()[$autoloadParamPosition]->value;
97
        $propertyNameValueExpr = $node->getArgs()[$propertyNameParamPosition]->value;
98
99
        if ($scope->getType($autoloadValueExpr)->isTrue()->yes()) {
100
            $constant = $definitionClassReflection->getConstant('ENTITY_NAME');
101
102
            if ($constant === false) {
103
                return [];
104
            }
105
106
            $propType = $scope->getType($propertyNameValueExpr);
107
            if (!$propType instanceof ConstantStringType) {
108
                return [];
109
            }
110
111
            return [
112
                RuleErrorBuilder::message(sprintf(
113
                    '%s.%s association has a configured autoload===true, this is forbidden for platform integrations',
114
                    $constant,
115
                    $propType->getValue()
116
                ))->build(),
117
            ];
118
        }
119
120
        return [];
121
    }
122
}
123