Passed
Push — master ( 640715...646380 )
by Jesse
01:33
created

ObjectExtractor::objectState()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 26
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 14
nc 6
nop 5
dl 0
loc 26
rs 9.4888
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace Stratadox\EntityState\Internal;
4
5
use function array_merge as these;
6
use function assert;
7
use function is_object;
8
use Stratadox\EntityState\PropertyState;
9
use Stratadox\Specification\Contract\Satisfiable;
10
11
final class ObjectExtractor implements Extractor
12
{
13
    private $next;
14
    private $stringifier;
15
16
    private function __construct(Extractor $next, Satisfiable $constraint)
17
    {
18
        $this->next = $next;
19
        $this->stringifier = $constraint;
20
    }
21
22
    public static function withAlternative(Extractor $next): Extractor
23
    {
24
        return new self($next, Unsatisfiable::constraint());
25
    }
26
27
    public static function stringifyingWithAlternative(
28
        Satisfiable $constraint,
29
        Extractor $next
30
    ): Extractor {
31
        return new self($next, $constraint);
32
    }
33
34
    public function extract(
35
        ExtractionRequest $request,
36
        Extractor $base = null
37
    ): array {
38
        if (!is_object($request->value())) {
39
            return $this->next->extract($request, $base);
40
        }
41
        if ($this->stringifier->isSatisfiedBy($request->value())) {
42
            return [PropertyState::with(
43
                (string) $request->objectName(),
44
                (string) $request->value()
45
            )];
46
        }
47
        if ($request->pointsToAnotherEntity()) {
48
            return [PropertyState::with(
49
                (string) $request->objectName(),
50
                $request->otherEntityId()
51
            )];
52
        }
53
        assert($base !== null);
54
        $properties = [];
55
        foreach (ReflectionProperties::ofThe($request->value()) as $property) {
56
            $properties[] = $base->extract(
57
                $request->forProperty($property),
58
                $base
59
            );
60
        }
61
        if (empty($properties)) {
62
            return $request->isTheOwner() ?
63
                [] :
64
                [PropertyState::with((string) $request->objectName(), null)];
65
        }
66
        return these(...$properties);
67
    }
68
}
69