Completed
Branch feature/pre-split (e38ab3)
by Anton
03:29
created

RecordInstantiator::identify()   B

Complexity

Conditions 5
Paths 12

Size

Total Lines 20
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 10
nc 12
nop 1
dl 0
loc 20
rs 8.8571
c 0
b 0
f 0
1
<?php
2
/**
3
 * components
4
 *
5
 * @author    Wolfy-J
6
 */
7
namespace Spiral\ORM\Entities;
8
9
use Spiral\Models\EntityInterface;
10
use Spiral\ORM\Exceptions\InstantionException;
11
use Spiral\ORM\InstantiatorInterface;
12
use Spiral\ORM\ORMInterface;
13
use Spiral\ORM\RecordEntity;
14
15
/**
16
 * Default instantiator for records.
17
 */
18
class RecordInstantiator implements InstantiatorInterface
19
{
20
    /**
21
     * @invisible
22
     * @var ORMInterface
23
     */
24
    private $orm;
25
26
    /**
27
     * Record class.
28
     *
29
     * @var string
30
     */
31
    private $class = '';
32
33
    /**
34
     * Normalized schema delivered by RecordSchema.
35
     *
36
     * @var array
37
     */
38
    private $schema = [];
39
40
    /**
41
     * @param ORMInterface $orm
42
     * @param string       $class
43
     * @param array        $schema
44
     */
45
    public function __construct(ORMInterface $orm, string $class, array $schema)
46
    {
47
        $this->orm = $orm;
48
        $this->class = $class;
49
        $this->schema = $schema;
50
    }
51
52
    /**
53
     * {@inheritdoc}
54
     */
55
    public function identify($fields)
56
    {
57
        if (!is_array($fields)) {
58
            $fields = iterator_to_array($fields);
59
        }
60
61
        $primaryKeys = [];
62
        foreach ($this->schema[RecordEntity::SH_PRIMARIES] as $primaryKey) {
63
            if (array_key_exists($primaryKey, $fields)) {
64
                $primaryKeys[] = $fields[$primaryKey];
65
            }
66
        }
67
68
        if (count($primaryKeys) === 0) {
69
            //Unable to create reliable identity
70
            return null;
71
        }
72
73
        return join('.', $primaryKeys);
74
    }
75
76
    /**
77
     * {@inheritdoc}
78
     *
79
     * @return EntityInterface
80
     *
81
     * @throws InstantionException
82
     */
83
    public function make($fields, int $state): EntityInterface
84
    {
85
        if (!is_array($fields)) {
86
            $fields = iterator_to_array($fields);
87
        }
88
89
        $class = $this->class;
90
91
        //Now we can construct needed class, in this case we are following DocumentEntity declaration
92
        if ($state == ORMInterface::STATE_LOADED) {
93
            //No need to filter values, passing directly in constructor
94
            return new $class($fields, $this->schema, $this->orm);
95
        }
96
97
        if ($state != ORMInterface::STATE_NEW) {
98
            throw new InstantionException(
99
                "Undefined state {$state}, only NEW and LOADED are supported"
100
            );
101
        }
102
103
        /*
104
         * Filtering entity
105
         */
106
107
        $entity = new $class([], $this->schema, $this->orm);
108
        if (!$entity instanceof RecordEntity) {
109
            throw new InstantionException(
110
                "Unable to set filtered values for '{$class}', must be instance of RecordEntity"
111
            );
112
        }
113
114
        //Must pass value thought all needed filters
115
        $entity->stateValue($fields);
116
117
        return $entity;
118
    }
119
120
}
121