Completed
Branch feature/split-orm (60a911)
by Anton
03:15
created

DocumentInstantiator   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 88
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
dl 0
loc 88
rs 10
c 0
b 0
f 0
wmc 8
lcom 1
cbo 1

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A instantiate() 0 12 2
B defineClass() 0 26 5
1
<?php
2
/**
3
 * components
4
 *
5
 * @author    Wolfy-J
6
 */
7
namespace Spiral\ODM\Entities;
8
9
use Spiral\ODM\CompositableInterface;
10
use Spiral\ODM\Document;
11
use Spiral\ODM\DocumentEntity;
12
use Spiral\ODM\Exceptions\DefinitionException;
13
use Spiral\ODM\InstantiatorInterface;
14
use Spiral\ODM\ODMInterface;
15
16
/**
17
 * Provides ability to construct Document and DocumentEntities with inheritance support.
18
 */
19
class DocumentInstantiator implements InstantiatorInterface
20
{
21
    /**
22
     * @invisible
23
     * @var ODMInterface
24
     */
25
    private $odm;
26
27
    /**
28
     * Primary instantiation class.
29
     *
30
     * @var string
31
     */
32
    private $class = '';
33
34
    /**
35
     * Normalized schema delivered by DocumentSchema.
36
     *
37
     * @var array
38
     */
39
    private $schema = [];
40
41
    /**
42
     * @param ODMInterface $odm
43
     * @param string       $class
44
     * @param array        $schema
45
     */
46
    public function __construct(ODMInterface $odm, string $class, array $schema)
47
    {
48
        $this->odm = $odm;
49
        $this->class = $class;
50
        $this->schema = $schema;
51
    }
52
53
    /**
54
     * @param array|\ArrayAccess $fields
55
     *
56
     * @return CompositableInterface|DocumentEntity|Document
57
     */
58
    public function instantiate($fields): CompositableInterface
59
    {
60
        $class = $this->defineClass($fields);
61
62
        if ($class !== $this->class) {
63
            //We have to dedicate class creation to external instantiator (possibly children class)
64
            return $this->odm->instantiate($class, $fields);
0 ignored issues
show
Bug introduced by
It seems like $fields defined by parameter $fields on line 58 can also be of type object<ArrayAccess>; however, Spiral\ODM\ODMInterface::instantiate() does only seem to accept array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
65
        }
66
67
        //Now we can construct needed class, in this case we are following DocumentEntity declaration
68
        return new $class($fields, $this->schema, $this->odm);
69
    }
70
71
    /**
72
     * Define document class using it's fieldset and definition.
73
     *
74
     * @param \ArrayAccess|array $fields
75
     *
76
     * @return string
77
     *
78
     * @throws DefinitionException
79
     */
80
    protected function defineClass($fields)
81
    {
82
        //Rule to define class instance
83
        $definition = $this->schema[DocumentEntity::SH_INSTANTIATION];
84
85
        if (is_string($definition)) {
86
            //Document has no variations
87
            return $definition;
88
        }
89
90
        if (!is_array($fields)) {
91
            //Unable to resolve for non array set, using same class as given
92
            return $this->class;
93
        }
94
95
        $defined = $this->class;
96
        foreach ($definition as $field => $child) {
97
            if (array_key_exists($field, $fields)) {
98
                //Apparently this is child
99
                $defined = $child;
100
                break;
101
            }
102
        }
103
104
        return $defined;
105
    }
106
}