RelationFactory::build()   B
last analyzed

Complexity

Conditions 6
Paths 9

Size

Total Lines 28
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
c 5
b 0
f 0
dl 0
loc 28
rs 8.439
cc 6
eloc 21
nc 9
nop 2
1
<?php
2
3
/*
4
* This file is part of the moss-storage package
5
*
6
* (c) Michal Wachowski <[email protected]>
7
*
8
* For the full copyright and license information, please view the LICENSE
9
* file that was distributed with this source code.
10
*/
11
12
namespace Moss\Storage\Query\Relation;
13
14
use Moss\Storage\Model\Definition\RelationInterface as RelationDefinitionInterface;
15
use Moss\Storage\Model\ModelBag;
16
use Moss\Storage\Model\ModelInterface;
17
use Moss\Storage\Query\QueryException;
18
use Moss\Storage\Query\StorageInterface;
19
20
/**
21
 * Entity relationship factory
22
 *
23
 * @author  Michal Wachowski <[email protected]>
24
 * @package Moss\Storage
25
 */
26
class RelationFactory implements RelationFactoryInterface
27
{
28
    const RELATION_ONE = 'one';
29
    const RELATION_MANY = 'many';
30
    const RELATION_ONE_TROUGH = 'oneTrough';
31
    const RELATION_MANY_TROUGH = 'manyTrough';
32
33
    /**
34
     * @var StorageInterface
35
     */
36
    protected $storage;
37
38
    /**
39
     * @var ModelBag
40
     */
41
    protected $bag;
42
43
    /**
44
     * Constructor
45
     *
46
     * @param StorageInterface $storage
47
     * @param ModelBag         $models
48
     */
49
    public function __construct(StorageInterface $storage, ModelBag $models)
50
    {
51
        $this->storage = $storage;
52
        $this->bag = $models;
53
    }
54
55
    /**
56
     * Sets model and its relation
57
     *
58
     * @param ModelInterface $model
59
     * @param string         $relation
60
     *
61
     * @return RelationInterface
62
     * @throws RelationException
63
     */
64
    public function build(ModelInterface $model, $relation)
65
    {
66
        list($current, $further) = $this->splitRelationName($relation);
67
        $definition = $this->fetchDefinition($model, $current);
68
69
        switch ($definition->type()) {
70
            case self::RELATION_ONE:
71
                $instance = new OneRelation($this->storage, $definition, $this->bag, $this);
72
                break;
73
            case self::RELATION_MANY:
74
                $instance = new ManyRelation($this->storage, $definition, $this->bag, $this);
75
                break;
76
            case self::RELATION_ONE_TROUGH:
77
                $instance = new OneTroughRelation($this->storage, $definition, $this->bag, $this);
78
                break;
79
            case self::RELATION_MANY_TROUGH:
80
                $instance = new ManyTroughRelation($this->storage, $definition, $this->bag, $this);
81
                break;
82
            default:
83
                throw new RelationException(sprintf('Invalid relation type "%s" for "%s"', $definition->type(), $definition->entity()));
84
        }
85
86
        if ($further) {
87
            $instance->with($further);
88
        }
89
90
        return $instance;
91
    }
92
93
    /**
94
     * Fetches relation
95
     *
96
     * @param ModelInterface $model
97
     * @param string         $relation
98
     *
99
     * @return RelationDefinitionInterface
100
     * @throws QueryException
101
     */
102
    protected function fetchDefinition(ModelInterface $model, $relation)
103
    {
104
        if ($model->hasRelation($relation)) {
105
            return $model->relation($relation);
106
        }
107
108
        throw new RelationException(sprintf('Unable to resolve relation "%s" not found in model "%s"', $relation, $model->entity()));
109
    }
110
111
    /**
112
     * Splits relation name
113
     *
114
     * @param string $relationName
115
     *
116
     * @return array
117
     */
118
    public function splitRelationName($relationName)
119
    {
120
        if (strpos($relationName, '.') !== false) {
121
            return explode('.', $relationName, 2);
122
        }
123
124
        return [$relationName, null];
125
    }
126
}
127