Completed
Push — master ( 057ffe...a55d6c )
by Jesse
02:02
created

Objects::addToMapIfNew()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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