Passed
Push — master ( 94f1d9...2d4769 )
by Pieter
02:23
created

IdentifierExtractor::getIdentifierKeyOfClass()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 26
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 18
nc 6
nop 2
dl 0
loc 26
rs 9.3554
c 0
b 0
f 0
1
<?php
2
namespace W2w\Lib\Apie;
3
4
use ReflectionException;
5
use ReflectionMethod;
6
use ReflectionProperty;
7
use Symfony\Component\PropertyAccess\PropertyAccessor;
8
9
/**
10
 * Extracts the identifier from a resource.
11
 */
12
class IdentifierExtractor
13
{
14
    private $propertyAccessor;
15
16
    public function __construct(PropertyAccessor $propertyAccessor)
17
    {
18
        $this->propertyAccessor = $propertyAccessor;
19
    }
20
21
    /**
22
     * Determines the identifier from a class without having an instance of the class.
23
     *
24
     * @param string $className
25
     * @param array $context
26
     * @return string|null
27
     */
28
    public function getIdentifierKeyOfClass(string $className, array $context = []): ?string
29
    {
30
        if (!empty($context['identifier'])) {
31
            return $context['identifier'];
32
        }
33
        $todo = [
34
            [ReflectionMethod::class, 'getId', 'id'],
35
            [ReflectionMethod::class, 'id', 'id'],
36
            [ReflectionProperty::class, 'id', 'id'],
37
            [ReflectionMethod::class, 'getUuid', 'uuid'],
38
            [ReflectionMethod::class, 'uuid', 'uuid'],
39
            [ReflectionProperty::class, 'uuid', 'uuid'],
40
        ];
41
        while (!empty($todo)) {
42
            list($reflectionClass, $property, $result) = array_shift($todo);
43
            try {
44
                /** @var ReflectionProperty|ReflectionMethod $test */
45
                $test = new $reflectionClass($className, $property);
46
                if ($test->isPublic()) {
47
                    return $result;
48
                }
49
            } catch (ReflectionException $e) {
50
                $e->getMessage();//ignore
51
            }
52
        }
53
        return null;
54
    }
55
56
    /**
57
     * Returns the name of the identifier of a resource. If it could not be determined,
58
     * it returns null.
59
     *
60
     * @param mixed $resource
61
     * @param array $context
62
     * @return string|null
63
     */
64
    public function getIdentifierKey($resource, array $context = []): ?string
65
    {
66
        if (isset($context['identifier'])) {
67
            return $context['identifier'];
68
        }
69
        foreach (['id', 'uuid'] as $id) {
70
            if ($this->propertyAccessor->isReadable($resource, $id)) {
71
                return $id;
72
            }
73
        }
74
        return null;
75
    }
76
77
    /**
78
     * Return the value of the identifer of a resource.
79
     *
80
     * @param mixed $resource
81
     * @param array $context
82
     * @return mixed|null
83
     */
84
    public function getIdentifierValue($resource, array $context = [])
85
    {
86
        $key = $this->getIdentifierKey($resource, $context);
87
        if (empty($key)) {
88
            return null;
89
        }
90
        return $this->propertyAccessor->getValue($resource, $key);
91
    }
92
}
93