Passed
Pull Request — master (#168)
by Aleksei
02:38
created

BelongsToLoader::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 4
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Cycle DataMapper ORM
5
 *
6
 * @license   MIT
7
 * @author    Anton Titov (Wolfy-J)
8
 */
9
10
declare(strict_types=1);
11
12
namespace Cycle\ORM\Select\Loader;
13
14
use Cycle\ORM\ORMInterface;
15
use Cycle\ORM\Parser\AbstractNode;
16
use Cycle\ORM\Parser\SingularNode;
17
use Cycle\ORM\Parser\Typecast;
18
use Cycle\ORM\Relation;
19
use Cycle\ORM\Schema;
20
use Cycle\ORM\Select\JoinableLoader;
21
use Cycle\ORM\Select\Traits\OrderByTrait;
22
use Cycle\ORM\Select\Traits\WhereTrait;
23
use Spiral\Database\Injection\Parameter;
24
use Spiral\Database\Query\SelectQuery;
25
26
/**
27
 * Load parent data. Similar to HasOne but use POSTLOAD as default method.
28
 */
29
class BelongsToLoader extends JoinableLoader
30
{
31
    use OrderByTrait;
32
    use WhereTrait;
33
34
    /**
35
     * Default set of relation options. Child implementation might defined their of default options.
36
     *
37
     * @var array
38
     */
39
    protected $options = [
40
        'load'      => false,
41
        'constrain' => true,
42
        'method'    => self::POSTLOAD,
43
        'minify'    => true,
44
        'as'        => null,
45
        'using'     => null,
46
        'where'     => null,
47
        'orderBy'   => null,
48
    ];
49
50
    /**
51
     * {@inheritdoc}
52
     */
53
    public function __construct(ORMInterface $orm, string $name, string $target, array $schema)
54
    {
55
        parent::__construct($orm, $name, $target, $schema);
56
        $this->options['where'] = $schema[Relation::WHERE] ?? [];
57
        $this->options['orderBy'] = $schema[Relation::ORDER_BY] ?? [];
58
    }
59
60
    /**
61
     * {@inheritdoc}
62
     */
63
    public function configureQuery(SelectQuery $query, array $outerKeys = []): SelectQuery
64
    {
65
        if ($this->options['using'] !== null) {
66
            // use pre-defined query
67
            return parent::configureQuery($query, $outerKeys);
68
        }
69
70
        $localKey = $this->localKey(Relation::OUTER_KEY);
71
72
        if ($this->isJoined()) {
73
            $query->join(
74
                $this->getJoinMethod(),
75
                $this->getJoinTable()
76
            )->on(
77
                $localKey,
78
                $this->parentKey(Relation::INNER_KEY)
79
            );
80
        } else {
81
            // relation is loaded using external query
82
            $query->where($localKey, 'IN', new Parameter($outerKeys));
83
        }
84
85
        // user specified WHERE conditions
86
        $this->setWhere(
87
            $query,
88
            $this->getAlias(),
89
            $this->isJoined() ? 'onWhere' : 'where',
90
            $this->options['where'] ?? $this->schema[Relation::WHERE] ?? []
91
        );
92
93
        // user specified ORDER_BY rules
94
        $this->setOrderBy(
95
            $query,
96
            $this->getAlias(),
97
            $this->options['orderBy'] ?? $this->schema[Relation::ORDER_BY] ?? []
98
        );
99
100
        return parent::configureQuery($query);
101
    }
102
103
    /**
104
     * {@inheritdoc}
105
     */
106
    protected function initNode(): AbstractNode
107
    {
108
        $node = new SingularNode(
109
            $this->columnNames(),
110
            $this->define(Schema::PRIMARY_KEY),
111
            $this->schema[Relation::OUTER_KEY],
112
            $this->schema[Relation::INNER_KEY]
113
        );
114
115
        $typecast = $this->define(Schema::TYPECAST);
116
        if ($typecast !== null) {
117
            $node->setTypecast(new Typecast($typecast, $this->getSource()->getDatabase()));
118
        }
119
120
        return $node;
121
    }
122
}
123