FallbackFactory   A
last analyzed

Complexity

Total Complexity 20

Size/Duplication

Total Lines 104
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 37
c 1
b 0
f 0
dl 0
loc 104
rs 10
wmc 20

8 Methods

Rating   Name   Duplication   Size   Complexity  
A getApiResourcePersisterInstance() 0 10 3
A createClassWithoutConstructorArguments() 0 11 4
A hasApiResourceRetrieverInstance() 0 3 2
A __construct() 0 6 1
A getApiResourceRetrieverInstance() 0 10 3
A isClassWithoutConstructorArguments() 0 8 3
A hasApiResourcePersisterInstance() 0 3 2
A getMemoryDataLayer() 0 9 2
1
<?php
2
3
namespace Apie\CorePlugin\ResourceFactories;
4
5
use Apie\Core\Exceptions\CouldNotConstructApiResourceClassException;
6
use Apie\Core\Exceptions\InvalidClassTypeException;
7
use Apie\Core\IdentifierExtractor;
8
use Apie\Core\Interfaces\ApiResourceFactoryInterface;
9
use Apie\Core\Interfaces\ApiResourcePersisterInterface;
10
use Apie\Core\Interfaces\ApiResourceRetrieverInterface;
11
use Apie\CorePlugin\DataLayers\MemoryDataLayer;
12
use Apie\ObjectAccessNormalizer\ObjectAccess\ObjectAccessInterface;
13
use ReflectionClass;
14
use ReflectionException;
15
16
class FallbackFactory implements ApiResourceFactoryInterface
17
{
18
    private $propertyAccessor;
19
20
    private $identifierExtractor;
21
22
    private $memoryDataLayer;
23
24
    public function __construct(
25
        ObjectAccessInterface $propertyAccessor,
26
        IdentifierExtractor $identifierExtractor
27
    ) {
28
        $this->propertyAccessor = $propertyAccessor;
29
        $this->identifierExtractor = $identifierExtractor;
30
    }
31
32
    private function getMemoryDataLayer(): MemoryDataLayer
33
    {
34
        if (!$this->memoryDataLayer) {
35
            $this->memoryDataLayer = new MemoryDataLayer(
36
                $this->propertyAccessor,
37
                $this->identifierExtractor
38
            );
39
        }
40
        return $this->memoryDataLayer;
41
    }
42
43
    /**
44
     * Returns true if this factory can create this identifier.
45
     *
46
     * @param string $identifier
47
     * @return bool
48
     */
49
    public function hasApiResourceRetrieverInstance(string $identifier): bool
50
    {
51
        return  $identifier === MemoryDataLayer::class || $this->isClassWithoutConstructorArguments($identifier);
52
    }
53
54
    /**
55
     * Gets an instance of ApiResourceRetrieverInstance
56
     * @param string $identifier
57
     * @return ApiResourceRetrieverInterface
58
     */
59
    public function getApiResourceRetrieverInstance(string $identifier): ApiResourceRetrieverInterface
60
    {
61
        if ($identifier === MemoryDataLayer::class) {
62
            return $this->getMemoryDataLayer();
63
        }
64
        $retriever = $this->createClassWithoutConstructorArguments($identifier);
65
        if (!$retriever instanceof ApiResourceRetrieverInterface) {
66
            throw new InvalidClassTypeException($identifier, 'ApiResourceRetrieverInterface');
67
        }
68
        return $retriever;
69
    }
70
71
    /**
72
     * Returns true if this factory can create this identifier.
73
     *
74
     * @param string $identifier
75
     * @return bool
76
     */
77
    public function hasApiResourcePersisterInstance(string $identifier): bool
78
    {
79
        return $identifier === MemoryDataLayer::class || $this->isClassWithoutConstructorArguments($identifier);
80
    }
81
82
    /**
83
     * Gets an instance of ApiResourceRetrieverInstance
84
     * @param string $identifier
85
     * @return ApiResourcePersisterInterface
86
     */
87
    public function getApiResourcePersisterInstance(string $identifier): ApiResourcePersisterInterface
88
    {
89
        if ($identifier === MemoryDataLayer::class) {
90
            return $this->getMemoryDataLayer();
91
        }
92
        $retriever = $this->createClassWithoutConstructorArguments($identifier);
93
        if (!$retriever instanceof ApiResourcePersisterInterface) {
94
            throw new InvalidClassTypeException($identifier, 'ApiResourcePersisterInterface');
95
        }
96
        return $retriever;
97
    }
98
99
    private function isClassWithoutConstructorArguments(string $identifier): bool
100
    {
101
        try {
102
            $reflClass = new ReflectionClass($identifier);
103
        } catch (ReflectionException $reflectionException) {
104
            return false;
105
        }
106
        return !$reflClass->getConstructor() || $reflClass->getConstructor()->getNumberOfRequiredParameters() === 0;
107
    }
108
109
    private function createClassWithoutConstructorArguments(string $identifier): object
110
    {
111
        try {
112
            $reflClass = new ReflectionClass($identifier);
113
        } catch (ReflectionException $reflectionException) {
114
            throw new CouldNotConstructApiResourceClassException($identifier, $reflectionException);
115
        }
116
        if ($reflClass->getConstructor() && $reflClass->getConstructor()->getNumberOfRequiredParameters() > 0) {
117
            throw new CouldNotConstructApiResourceClassException($identifier);
118
        }
119
        return new $identifier();
120
    }
121
}
122