Passed
Push — master ( 8e9a90...99a21b )
by Mr
02:07
created

FromToNativeTrait   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 77
Duplicated Lines 0 %

Test Coverage

Coverage 56.1%

Importance

Changes 10
Bugs 0 Features 1
Metric Value
wmc 16
eloc 43
c 10
b 0
f 1
dl 0
loc 77
ccs 23
cts 41
cp 0.561
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
B construct() 0 30 7
A fromNative() 0 14 4
A toNative() 0 21 5
1
<?php declare(strict_types=1);
2
/**
3
 * This file is part of the daikon-cqrs/interop project.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
9
namespace Daikon\Interop;
10
11
use ReflectionClass;
12
13
trait FromToNativeTrait
14
{
15
    use SupportsAnnotations;
0 ignored issues
show
Bug introduced by
The type Daikon\Interop\SupportsAnnotations 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...
16
17
    /**
18
     * @psalm-suppress MissingParamType
19
     * @return static
20
     */
21 11
    public static function fromNative($state): self
22
    {
23 11
        Assertion::isArray($state, 'This trait only works with array state.');
24
25 7
        list($valueFactories, $product) = static::construct($state);
26 6
        foreach ($valueFactories as $propertyName => $factory) {
27 4
            if (array_key_exists($propertyName, $state)) {
28 3
                $product->$propertyName = $factory($state[$propertyName]);
29 2
            } elseif (is_a($factory[0], MakeEmptyInterface::class, true)) {
30 2
                $product->$propertyName = ([$factory[0], 'makeEmpty'])();
31
            }
32
        }
33
34 4
        return $product;
35
    }
36
37
    public function toNative(): array
38
    {
39
        $state = [];
40
        $reflectionClass = new ReflectionClass($this);
41
        foreach (static::getInheritance() as $currentClass) {
42
            foreach ($currentClass->getProperties() as $property) {
43
                $propertyName = $property->getName();
44
                if ($currentClass->isTrait()) {
45
                    $property = $reflectionClass->getProperty($propertyName);
46
                }
47
                $property->setAccessible(true);
48
                $value = $property->getValue($this);
49
                if (is_a($value, ToNativeInterface::class)) {
50
                    $state[$propertyName] = $value->toNative();
51
                } else {
52
                    $state[$propertyName] = $value;
53
                }
54
            }
55
        }
56
57
        return $state;
58
    }
59
60 7
    private static function construct(array $payload): array
61
    {
62 7
        $valueFactories = static::inferValueFactories();
63 7
        $constructor = (new ReflectionClass(static::class))->getConstructor();
64 7
        if (is_null($constructor) || $constructor->getNumberOfParameters() === 0) {
65
            /** @psalm-suppress TooFewArguments */
66 4
            return [$valueFactories, new static];
67
        }
68
69 4
        $constructorArgs = [];
70 4
        foreach ($constructor->getParameters() as $constructorParam) {
71 4
            $paramName = $constructorParam->getName();
72 4
            if (isset($payload[$paramName])) {
73 3
                if (isset($valueFactories[$paramName])) {
74
                    $constructorArgs[] = $valueFactories[$paramName]($payload[$paramName]);
75
                    unset($valueFactories[$paramName]);
76
                } else {
77 3
                    $constructorArgs[] = $payload[$paramName];
78
                }
79 3
            } elseif ($constructorParam->allowsNull()) {
80 3
                $constructorArgs[] = null;
81
            } else {
82
                throw new InvalidArgumentException(
83
                    "Missing required value for key '$paramName' while constructing from native state."
84
                );
85
            }
86
        }
87
88
        /** @psalm-suppress TooManyArguments */
89 4
        return [$valueFactories, new static(...$constructorArgs)];
90
    }
91
}
92