Test Failed
Push — master ( 385400...b007ca )
by Michael
02:12
created

AbstractProcessor::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 6
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
declare(strict_types = 1);
3
4
namespace Mikemirten\Component\JsonApi\Mapper\Definition\AnnotationProcessor;
5
6
use Mikemirten\Component\JsonApi\Mapper\Definition\Annotation\Link as LinkAnnotation;
7
use Mikemirten\Component\JsonApi\Mapper\Definition\Link;
8
use Doctrine\Common\Annotations\AnnotationRegistry;
9
use Doctrine\Common\Annotations\Reader;
10
11
/**
12
 * Abstract processor
13
 * Contains shared methods and annotations registration
14
 *
15
 * @package Mikemirten\Component\JsonApi\Mapper\Definition\AnnotationProcessor
16
 */
17
abstract class AbstractProcessor implements AnnotationProcessorInterface
18
{
19
    /**
20
     * Pattern of "resource" parameter of link annotation
21
     */
22
    const RESOURCE_PATTERN = '~^(?<repository>[a-z_][a-z0-9_]*)\.(?<link>[a-z_][a-z0-9_]*)$~i';
23
24
    /**
25
     * Annotation classes ha been registered.
26
     *
27
     * @var bool
28
     */
29
    static private $annotationsRegistered = false;
30
31
    /**
32
     * Doctrine annotation reader
33
     *
34
     * @var Reader
35
     */
36
    protected $reader;
37
38
    /**
39
     * AnnotationDefinitionProvider constructor.
40
     *
41
     * @param Reader $reader
42
     */
43
    public function __construct(Reader $reader)
44
    {
45
        self::registerAnnotations();
46
47
        $this->reader = $reader;
48
    }
49
50
    /**
51
     * Register annotation classes.
52
     * Supports a medieval-aged way of "autoloading" for the Doctrine Annotation library.
53
     */
54
    static protected function registerAnnotations()
0 ignored issues
show
Coding Style introduced by
As per PSR2, the static declaration should come after the visibility declaration.
Loading history...
55
    {
56
        if (self::$annotationsRegistered === false) {
57
            AnnotationRegistry::registerFile(__DIR__ . '/../Annotation/ResourceIdentifier.php');
0 ignored issues
show
Deprecated Code introduced by
The method Doctrine\Common\Annotati...egistry::registerFile() has been deprecated with message: 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')

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

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

Loading history...
58
            AnnotationRegistry::registerFile(__DIR__ . '/../Annotation/Relationship.php');
0 ignored issues
show
Deprecated Code introduced by
The method Doctrine\Common\Annotati...egistry::registerFile() has been deprecated with message: 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')

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

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

Loading history...
59
            AnnotationRegistry::registerFile(__DIR__ . '/../Annotation/Attribute.php');
0 ignored issues
show
Deprecated Code introduced by
The method Doctrine\Common\Annotati...egistry::registerFile() has been deprecated with message: 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')

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

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

Loading history...
60
            AnnotationRegistry::registerFile(__DIR__ . '/../Annotation/Link.php');
0 ignored issues
show
Deprecated Code introduced by
The method Doctrine\Common\Annotati...egistry::registerFile() has been deprecated with message: 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')

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

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

Loading history...
61
62
            self::$annotationsRegistered = true;
63
        }
64
    }
65
66
    /**
67
     * Create link by link's annotation
68
     *
69
     * @param  LinkAnnotation $annotation
70
     * @return Link
71
     */
72
    protected function createLink(LinkAnnotation $annotation): Link
73
    {
74
        if (! preg_match(self::RESOURCE_PATTERN, $annotation->resource, $matches)) {
75
            throw new \LogicException(sprintf('Invalid resource definition: "%s"', $annotation->resource));
76
        }
77
78
        $link = new Link(
79
            $annotation->name,
80
            $matches['repository'],
81
            $matches['link']
82
        );
83
84
        $link->setParameters($annotation->parameters);
85
        $link->setMetadata($annotation->metadata);
86
87
        return $link;
88
    }
89
90
    /**
91
     * Resolve getter of related object
92
     *
93
     * @param  \ReflectionProperty $property
94
     * @return string
95
     */
96
    protected function resolveGetter(\ReflectionProperty $property)
97
    {
98
        $name  = $property->getName();
99
        $class = $property->getDeclaringClass();
100
101
        foreach (['get', 'is'] as $prefix)
102
        {
103
            $getter = $prefix . ucfirst($name);
104
105
            if ($class->hasMethod($getter) && $class->getMethod($getter)->isPublic()) {
106
                return $getter;
107
            }
108
        }
109
110
        throw new \LogicException(sprintf(
111
            'Getter-method for the property "%s" cannot be resolved automatically. ' .
112
            'Probably there is no get%2$s() or is%2$s() method or it is not public.',
113
            $name, ucfirst($name)
114
        ));
115
    }
116
117
    /**
118
     * Resolve getter of related object
119
     *
120
     * @param  \ReflectionProperty $property
121
     * @return string | null
122
     */
123
    protected function resolveSetter(\ReflectionProperty $property)
124
    {
125
        $name  = $property->getName();
126
        $class = $property->getDeclaringClass();
127
128
        $setter = 'set' . ucfirst($name);
129
130
        if ($class->hasMethod($setter) && $class->getMethod($setter)->isPublic()) {
131
            return $setter;
132
        }
133
    }
134
}