Issues (46)

src/Metadata/Factory.php (6 issues)

1
<?php
2
3
namespace Er1z\FakeMock\Metadata;
4
5
use Doctrine\Common\Annotations\AnnotationReader;
6
use Doctrine\Common\Annotations\AnnotationRegistry;
7
use Doctrine\Common\Annotations\Reader;
8
use Er1z\FakeMock\Annotations\AnnotationCollection;
9
use Er1z\FakeMock\Annotations\FakeMock;
10
use Er1z\FakeMock\Annotations\FakeMockField;
11
use phpDocumentor\Reflection\DocBlock\Tag;
12
use phpDocumentor\Reflection\Type;
13
use phpDocumentor\Reflection\Types\ContextFactory;
14
15
class Factory implements FactoryInterface
16
{
17
    protected $reader;
18
19 98
    public function __construct(?Reader $reader = null)
20
    {
21
        // can't wait for v2...
22 98
        if (class_exists(AnnotationRegistry::class)) {
23 98
            AnnotationRegistry::registerLoader('class_exists');
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\Common\Annotati...istry::registerLoader() has been deprecated: this method is deprecated and will be removed in doctrine/annotations 2.0 autoloading should be deferred to the globally registered autoloader by then. For now, use @example AnnotationRegistry::registerLoader('class_exists') ( Ignorable by Annotation )

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

23
            /** @scrutinizer ignore-deprecated */ AnnotationRegistry::registerLoader('class_exists');

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
24
        }
25
26 98
        $this->reader = $reader ?? new AnnotationReader();
27 98
    }
28
29 58
    public function getObjectConfiguration(\ReflectionClass $object): ?FakeMock
30
    {
31 58
        return $this->reader->getClassAnnotation($object, FakeMock::class);
32
    }
33
34
    /**
35
     * @param $object
36
     * @param FakeMock            $objectConfiguration
37
     * @param \ReflectionProperty $property
38
     *
39
     * @return FieldMetadata[]
40
     */
41 54
    public function create($object, FakeMock $objectConfiguration, \ReflectionProperty $property)
42
    {
43 54
        $annotations = new AnnotationCollection($this->reader->getPropertyAnnotations($property));
44 54
        $fieldAnnotations = $annotations->findAllBy(FakeMockField::class);
45
46 54
        if (!$fieldAnnotations) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $fieldAnnotations of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
47 8
            return null;
48
        }
49
50 46
        $result = [];
51
52 46
        foreach ($fieldAnnotations as $a) {
53 46
            $f = new FieldMetadata();
54 46
            $f->property = $property;
55 46
            $f->objectConfiguration = $objectConfiguration;
56 46
            $f->annotations = $annotations;
57 46
            $f->type = $this->getPhpDocType($property);
58 46
            $f->object = $object;
59 46
            $f->configuration = $this->mergeGlobalConfigurationWithLocal($objectConfiguration, $a);
60
61 46
            $result[] = $f;
62
        }
63
64 46
        return $result;
65
    }
66
67
    /**
68
     * @param FieldMetadata[] $annotations
69
     * @param string|null     $group
70
     *
71
     * @return FieldMetadata[]
72
     */
73 58
    public function getConfigurationForFieldByGroup($annotations, ?string $group = null)
74
    {
75 58
        if (empty($annotations)) {
76 8
            return null;
77
        }
78
79 50
        if (is_null($group)) {
80 42
            return array_shift($annotations);
81
        }
82
83
        $result = array_filter($annotations, function ($item) use ($group) {
84 12
            return !empty($item->configuration->groups) && in_array($group, $item->configuration->groups);
85 12
        });
86
87 12
        $filtered = array_values($result);
88
89 12
        return array_shift($filtered);
90
    }
91
92 50
    protected function mergeGlobalConfigurationWithLocal(FakeMock $objectConfig, FakeMockField $fieldConfig): FakeMockField
93
    {
94 50
        if (is_null($fieldConfig->useAsserts)) {
0 ignored issues
show
The condition is_null($fieldConfig->useAsserts) is always false.
Loading history...
95 46
            $fieldConfig->useAsserts = $objectConfig->useAsserts;
96
        }
97
98 50
        if (is_null($fieldConfig->satisfyAssertsConditions)) {
0 ignored issues
show
The condition is_null($fieldConfig->satisfyAssertsConditions) is always false.
Loading history...
99 50
            $fieldConfig->satisfyAssertsConditions = $objectConfig->satisfyAssertsConditions;
100
        }
101
102 50
        if (is_null($fieldConfig->recursive)) {
103 50
            $fieldConfig->recursive = $objectConfig->recursive;
104
        }
105
106 50
        if (is_null($fieldConfig->locale)) {
107 50
            $fieldConfig->locale = $objectConfig->locale;
108
        }
109
110 50
        return $fieldConfig;
111
    }
112
113 50
    protected function getPhpDocType(\ReflectionProperty $property): ?Type
114
    {
115 50
        $factory = \phpDocumentor\Reflection\DocBlockFactory::createInstance();
116 50
        $docComment = $property->getDocComment();
117
118 50
        if (!$docComment) {
119 4
            return null;
120
        }
121
122 50
        $ctxFactory = new ContextFactory();
123
124 50
        $data = $factory->create(
125 50
            $docComment, $ctxFactory->createFromReflector($property)
0 ignored issues
show
It seems like $docComment can also be of type true; however, parameter $docblock of phpDocumentor\Reflection\DocBlockFactory::create() does only seem to accept object|string, maybe add an additional type check? ( Ignorable by Annotation )

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

125
            /** @scrutinizer ignore-type */ $docComment, $ctxFactory->createFromReflector($property)
Loading history...
126
        );
127
128
        /**
129
         * @var $vars Tag[]
130
         */
131 50
        if ($vars = $data->getTagsByName('var')) {
132 30
            return $vars[0]->getType();
0 ignored issues
show
The method getType() does not exist on phpDocumentor\Reflection\DocBlock\Tag. It seems like you code against a sub-type of phpDocumentor\Reflection\DocBlock\Tag such as phpDocumentor\Reflection\DocBlock\Tags\Property or phpDocumentor\Reflection\DocBlock\Tags\Var_ or phpDocumentor\Reflection\DocBlock\Tags\Param or phpDocumentor\Reflection...lock\Tags\PropertyWrite or phpDocumentor\Reflection\DocBlock\Tags\Return_ or phpDocumentor\Reflection\DocBlock\Tags\Throws or phpDocumentor\Reflection...Block\Tags\PropertyRead. ( Ignorable by Annotation )

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

132
            return $vars[0]->/** @scrutinizer ignore-call */ getType();
Loading history...
133
        }
134
135 27
        return null;
136
    }
137
}
138