Passed
Branch 3.0.0 (dcfee6)
by Pieter
02:48
created

FallbackFactory   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 114
Duplicated Lines 0 %

Importance

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

7 Methods

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