Passed
Pull Request — master (#3)
by De Cramer
01:49
created

AbstractChainOperation::resolveMethodName()   A

Complexity

Conditions 6
Paths 6

Size

Total Lines 23
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 0
Metric Value
cc 6
eloc 13
c 0
b 0
f 0
nc 6
nop 1
dl 0
loc 23
ccs 0
cts 0
cp 0
crap 42
rs 9.2222
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Oliverde8\Component\PhpEtl\ChainOperation;
6
7
use Oliverde8\Component\PhpEtl\Item\DataItemInterface;
8
use Oliverde8\Component\PhpEtl\Item\ItemInterface;
9
use Oliverde8\Component\PhpEtl\Item\StopItem;
10
use Oliverde8\Component\PhpEtl\Model\ExecutionContext;
11
12
/**
13
 * Class AbstractChainOperation
14
 *
15
 * @author    de Cramer Oliver<[email protected]>
16
 * @copyright 2018 Oliverde8
17
 * @package Oliverde8\Component\PhpEtl\ChainOperation
18 13
 */
19
abstract class AbstractChainOperation implements ChainOperationInterface
20 13
{
21
    private $methodResolutionCache = [];
22 13
23 13
    /**
24
     * @inheritdoc
25
     */
26 4
    final public function process(ItemInterface $item, ExecutionContext $context): ItemInterface
27
    {
28
        if (!isset($this->methodResolutionCache[get_class($item)])) {
29
            $this->methodResolutionCache[get_class($item)] = $this->resolveMethodName($item);
30
        }
31
        $method = $this->methodResolutionCache[get_class($item)];
32
33
        if (!is_null($method)) {
34
            return $this->$method($item, $context);
35
        }
36
37
        return $item;
38
    }
39
40
    private function resolveMethodName(ItemInterface $item): ?string
41
    {
42
        $processReflection = new \ReflectionClass($this);
43
        foreach ($processReflection->getMethods() as $method) {
44
            if ($this->validateMethod($method)) {
45
                $firstParameter = $method->getParameters()[0];
46
                $expecting = $firstParameter->getType()->getName();
0 ignored issues
show
Bug introduced by
The method getName() does not exist on ReflectionType. It seems like you code against a sub-type of ReflectionType such as ReflectionNamedType. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

46
                $expecting = $firstParameter->getType()->/** @scrutinizer ignore-call */ getName();
Loading history...
47
48
                if (interface_exists($expecting)) {
49
                    $itemReflection = new \ReflectionClass($item);
50
                    if ($itemReflection->implementsInterface($expecting)) {
51
                        return  $method->getName();
52
                    }
53
                    continue;
54
                }
55
56
                if ($this->checkIsA(get_class($item), $expecting)) {
57
                    return $method->getName();
58
                }
59
            };
60
        }
61
62
        return null;
63
    }
64
65
    private function checkIsA(string $class, string $targetClass): bool
66
    {
67
        if ($class == $targetClass) {
68
            return true;
69
        }
70
71
        $parentClass = get_parent_class($class);
72
        if ($parentClass) {
73
            return $this->getExtensionDistance($parentClass, $targetClass);
0 ignored issues
show
Bug introduced by
The method getExtensionDistance() does not exist on Oliverde8\Component\PhpE...\AbstractChainOperation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

73
            return $this->/** @scrutinizer ignore-call */ getExtensionDistance($parentClass, $targetClass);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
74
        }
75
76
        return false;
77
    }
78
79
    private function validateMethod(\ReflectionMethod $method)
80
    {
81
        if (count($method->getParameters()) != 2) {
82
            return false;
83
        }
84
        if (in_array($method->getName(), ['process', 'resolveMethodName'])) {
85
            return false;
86
        }
87
        if (strpos($method->getName(), "process") !== 0) {
88
            return false;
89
        }
90
91
        return true;
92
    }
93
}
94