Passed
Branch 3.0.0 (98e096)
by Pieter
02:47
created

FallbackFactory::getApiResourceRetrieverInstance()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 18
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 13
c 1
b 0
f 0
nc 5
nop 1
dl 0
loc 18
rs 9.5222
1
<?php
2
3
4
namespace W2w\Lib\Apie\ResourceFactories;
5
6
use Symfony\Component\PropertyAccess\PropertyAccessor;
7
use W2w\Lib\Apie\ApiResourceFactoryInterface;
0 ignored issues
show
Bug introduced by
The type W2w\Lib\Apie\ApiResourceFactoryInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
Bug introduced by
This use statement conflicts with another class in this namespace, W2w\Lib\Apie\ResourceFac...esourceFactoryInterface. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
8
use W2w\Lib\Apie\Exceptions\CouldNotConstructApiResourceClassException;
9
use W2w\Lib\Apie\Exceptions\InvalidClassTypeException;
10
use W2w\Lib\Apie\IdentifierExtractor;
11
use W2w\Lib\Apie\Persisters\ApiResourcePersisterInterface;
12
use W2w\Lib\Apie\Retrievers\ApiResourceRetrieverInterface;
13
use W2w\Lib\Apie\Retrievers\ApplicationInfoRetriever;
14
use W2w\Lib\Apie\Retrievers\MemoryDataLayer;
15
use W2w\Lib\Apie\Retrievers\StatusCheckRetriever;
16
17
class FallbackFactory implements ApiResourceFactoryInterface
18
{
19
    private $propertyAccessor;
20
21
    private $identifierExtractor;
22
23
    private $debug;
24
25
    public function __construct(
26
        PropertyAccessor $propertyAccessor,
27
        IdentifierExtractor $identifierExtractor,
28
        bool $debug
29
    ) {
30
        $this->propertyAccessor = $propertyAccessor;
31
        $this->identifierExtractor = $identifierExtractor;
32
        $this->debug = $debug;
33
    }
34
35
    /**
36
     * Returns true if this factory can create this identifier.
37
     *
38
     * @param string $identifier
39
     * @return bool
40
     */
41
    public function hasApiResourceRetrieverInstance(string $identifier): bool
42
    {
43
        $defaultRetriever = in_array(
44
            $identifier,
45
            [
46
                ApplicationInfoRetriever::class,
47
                StatusCheckRetriever::class,
48
                MemoryDataLayer::class,
49
            ]
50
        );
51
        return $defaultRetriever || $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
        switch ($identifier) {
62
            case ApplicationInfoRetriever::class:
63
                return new ApplicationInfoRetriever('undefined', 'unknown', '-', $this->debug);
64
            case StatusCheckRetriever::class:
65
                return new StatusCheckRetriever([]);
66
            case MemoryDataLayer::class:
67
                return new MemoryDataLayer(
68
                    $this->propertyAccessor,
69
                    $this->identifierExtractor
70
                );
71
        }
72
        $retriever = $this->createClassWithoutConstructorArguments($identifier);
73
        if (!$retriever instanceof ApiResourceRetrieverInterface) {
74
            throw new InvalidClassTypeException($identifier, 'ApiResourceRetrieverInterface');
75
        }
76
        return $retriever;
77
    }
78
79
    /**
80
     * Returns true if this factory can create this identifier.
81
     *
82
     * @param string $identifier
83
     * @return bool
84
     */
85
    public function hasApiResourcePersisterInstance(string $identifier): bool
86
    {
87
        return $identifier === MemoryDataLayer::class || $this->isClassWithoutConstructorArguments($identifier);
88
    }
89
90
    /**
91
     * Gets an instance of ApiResourceRetrieverInstance
92
     * @param string $identifier
93
     * @return ApiResourcePersisterInterface
94
     */
95
    public function getApiResourcePersisterInstance(string $identifier): ApiResourcePersisterInterface
96
    {
97
        if ($identifier === MemoryDataLayer::class) {
98
            return new MemoryDataLayer(
99
                $this->propertyAccessor,
100
                $this->identifierExtractor
101
            );
102
        }
103
        $retriever = $this->createClassWithoutConstructorArguments($identifier);
104
        if (!$retriever instanceof ApiResourcePeristerInterface) {
0 ignored issues
show
Bug introduced by
The type W2w\Lib\Apie\ResourceFac...sourcePeristerInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
105
            throw new InvalidClassTypeException($identifier, 'ApiResourcePersisterInterface');
106
        }
107
        return $retriever;
108
    }
109
110
    private function isClassWithoutConstructorArguments(string $identifier): bool
111
    {
112
        try {
113
            $reflClass = new ReflectionClass($identifier);
0 ignored issues
show
Bug introduced by
The type W2w\Lib\Apie\ResourceFactories\ReflectionClass was not found. Did you mean ReflectionClass? If so, make sure to prefix the type with \.
Loading history...
114
        } catch (ReflectionException $reflectionException) {
0 ignored issues
show
Bug introduced by
The type W2w\Lib\Apie\ResourceFactories\ReflectionException was not found. Did you mean ReflectionException? If so, make sure to prefix the type with \.
Loading history...
115
            return false;
116
        }
117
        return !$reflClass->getConstructor() || $reflClass->getConstructor()->getNumberOfRequiredParameters() === 0;
118
    }
119
120
    private function createClassWithoutConstructorArguments(string $identifier): object
121
    {
122
        try {
123
            $reflClass = new ReflectionClass($identifier);
124
        } catch (ReflectionException $reflectionException) {
125
            throw new CouldNotConstructApiResourceClassException($identifier, $reflectionException);
126
        }
127
        if ($reflClass->getConstructor() && $reflClass->getConstructor()->getNumberOfRequiredParameters() > 0) {
128
            throw new CouldNotConstructApiResourceClassException($identifier);
129
        }
130
        return new $identifier();
131
    }
132
}
133