Completed
Branch feature/pre-split (ce4b6b)
by Anton
05:23
created

RelationManager::packRelations()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 7
nc 3
nop 1
dl 0
loc 13
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * components
4
 *
5
 * @author    Wolfy-J
6
 */
7
namespace Spiral\ORM\Schemas;
8
9
use Spiral\Core\FactoryInterface;
10
use Spiral\ORM\Configs\RelationsConfig;
11
use Spiral\ORM\Exceptions\DefinitionException;
12
use Spiral\ORM\Schemas\Definitions\RelationDefinition;
13
14
/**
15
 * Subsection of SchemaBuilder used to configure tables and columns defined by model to model
16
 * relations.
17
 */
18
class RelationManager
19
{
20
    /**
21
     * @invisible
22
     * @var RelationsConfig
23
     */
24
    protected $config;
25
26
    /**
27
     * @invisible
28
     * @var FactoryInterface
29
     */
30
    protected $factory;
31
32
    /**
33
     * Set of relation definitions.
34
     *
35
     * @var RelationInterface[]
36
     */
37
    private $relations = [];
38
39
    /**
40
     * @param RelationsConfig  $config
41
     * @param FactoryInterface $factory
42
     */
43
    public function __construct(RelationsConfig $config, FactoryInterface $factory)
44
    {
45
        $this->config = $config;
46
        $this->factory = $factory;
47
    }
48
49
    /**
50
     * Registering new relation definition.
51
     *
52
     * @param RelationDefinition $definition Relation options (definition).
53
     *
54
     * @throws DefinitionException
55
     */
56
    public function registerRelation(RelationDefinition $definition)
57
    {
58
        if (!$this->config->hasRelation($definition->getType())) {
59
            throw new DefinitionException(sprintf(
60
                "Undefined relation type '%s' in '%s'.'%s'",
61
                $definition->getType(),
62
                $definition->sourceContext()->getClass(),
63
                $definition->getName()
64
            ));
65
        }
66
67
        $class = $this->config->relationClass(
68
            $definition->getType(),
69
            RelationsConfig::SCHEMA_CLASS
70
        );
71
72
        //Creating relation schema
73
        $relation = $this->factory->make($class, compact('definition'));
74
75
        //Equavalent (low)?
1 ignored issue
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
76
77
        $this->relations[] = $relation;
78
    }
79
80
    /**
81
     * Create inverse relations where needed.
82
     *
83
     * @throws DefinitionException
84
     */
85
    public function inverseRelations()
86
    {
87
        /**
88
         * Inverse process is relation specific.
89
         */
90
        foreach ($this->relations as $relation) {
91
            $definition = $relation->getDefinition();
92
93
            if ($definition->needInversion()) {
94
                if (!$relation instanceof InversableRelationInterface) {
95
                    throw new DefinitionException(sprintf(
96
                        "Unable to inverse relation '%s'.'%s', relation schema '%s' non inversable",
97
                        $definition->sourceContext()->getClass(),
98
                        $definition->getName(),
99
                        get_class($relation)
100
                    ));
101
                }
102
103
                //Let's perform inversion
104
                $this->registerRelation($relation->inverseDefinition($definition->getInverse()));
105
            }
106
        }
107
    }
108
109
    //todo: normalize relations?
110
111
    /**
112
     * Declare set of tables for each relation. Method must return Generator of AbstractTable
113
     * sequentially (attention, non sequential processing will cause collision issues between
114
     * tables).
115
     *
116
     * @param SchemaBuilder $builder
117
     *
118
     * @return \Generator
119
     */
120
    public function declareTables(SchemaBuilder $builder): \Generator
121
    {
122
        foreach ($this->relations as $relation) {
123
            foreach ($relation->declareTables($builder) as $table) {
124
                yield $table;
125
            }
126
        }
127
    }
128
129
    /**
130
     * Pack relation schemas for specific model class in order to be saved in memory.
131
     *
132
     * @param string $class
133
     *
134
     * @return array
135
     */
136
    public function packRelations(string $class): array
137
    {
138
        $result = [];
139
        foreach ($this->relations as $relation) {
140
            $definition = $relation->getDefinition();
141
142
            if ($definition->sourceContext()->getClass() == $class) {
143
                $result[$definition->getName()] = $relation->packRelation();
144
            }
145
        }
146
147
        return $result;
148
    }
149
}