Objects::producedByThis()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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