Completed
Push — master ( 85c19c...2798ac )
by Jesse
02:11
created

Objects::from()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 22
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 22
rs 8.6737
c 0
b 0
f 0
cc 5
eloc 17
nc 8
nop 2
1
<?php
2
declare(strict_types=1);
3
4
namespace Stratadox\TableLoader;
5
6
use function is_null;
7
use Stratadox\Hydrator\CannotHydrate;
8
use Stratadox\Hydrator\Hydrates;
9
use Stratadox\IdentityMap\AlreadyThere;
10
use Stratadox\IdentityMap\MapsObjectsByIdentity as Map;
11
use Throwable;
12
13
/**
14
 * Makes partially hydrated objects from an input array.
15
 *
16
 * @author Stratadox
17
 */
18
final class Objects implements MakesObjects
19
{
20
    private $hydrate;
21
    private $relevantData;
22
    private $identifier;
23
24
    private function __construct(
25
        Hydrates $theObjects,
26
        FiltersTheArray $toTheRelevantDataOnly,
27
        IdentifiesEntities $forIndexation
28
    ) {
29
        $this->hydrate = $theObjects;
30
        $this->relevantData = $toTheRelevantDataOnly;
31
        $this->identifier = $forIndexation;
32
    }
33
34
    /**
35
     * Makes a new object extractor that produces partially hydrated objects.
36
     *
37
     * @param Hydrates           $theObjects            Hydrator for the objects.
38
     * @param FiltersTheArray    $toTheRelevantDataOnly The filter for the input
39
     *                                                  array.
40
     * @param IdentifiesEntities $forIndexation         The row identification
41
     *                                                  mechanism.
42
     * @return MakesObjects                             The object extractor.
43
     */
44
    public static function producedByThis(
45
        Hydrates $theObjects,
46
        FiltersTheArray $toTheRelevantDataOnly,
47
        IdentifiesEntities $forIndexation
48
    ): MakesObjects {
49
        return new self($theObjects, $toTheRelevantDataOnly, $forIndexation);
50
    }
51
52
    /** @inheritdoc */
53
    public function from(array $input, Map $map): ContainsResultingObjects {
54
        $data = $this->relevantData->only($input);
55
        $label = $this->relevantData->label();
56
        $objects = [];
57
        foreach ($data as $row) {
58
            if ($this->identifier->isNullFor($row)) {
59
                continue;
60
            }
61
            $hash = $this->identifier->forLoading($row);
62
            if (isset($objects[$hash])) {
63
                continue;
64
            }
65
            try {
66
                $class = $this->hydrate->classFor($row);
67
                $id = $this->identifier->forIdentityMap($row);
68
                $map = $this->addToMapIfNew($class, $id, $row, $map);
69
                $objects[$hash] = $map->get($class, $id);
70
            } catch (Throwable $exception) {
71
                throw UnmappableRow::encountered($exception, $label, $row);
72
            }
73
        }
74
        return Result::fromArray([$label => $objects], $map);
75
    }
76
77
    /** @throws CannotHydrate|AlreadyThere */
78
    private function addToMapIfNew(
79
        string $class,
80
        string $id,
81
        array $row,
82
        Map $map
83
    ): Map {
84
        if (!$map->has($class, $id)) {
85
            $map = $map->add($id, $this->hydrate->fromArray($row));
86
        }
87
        return $map;
88
    }
89
}
90