Passed
Push — master ( d32cb5...b51066 )
by Anton
04:06 queued 12s
created

HasManyLoader::initNode()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 9
nc 2
nop 0
dl 0
loc 15
rs 9.9666
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\Exception\LoaderException;
15
use Cycle\ORM\ORMInterface;
16
use Cycle\ORM\Parser\AbstractNode;
17
use Cycle\ORM\Parser\ArrayNode;
18
use Cycle\ORM\Parser\Typecast;
19
use Cycle\ORM\Relation;
20
use Cycle\ORM\Schema;
21
use Cycle\ORM\Select\JoinableLoader;
22
use Cycle\ORM\Select\Traits\WhereTrait;
23
use Spiral\Database\Injection\Parameter;
24
use Spiral\Database\Query\SelectQuery;
25
26
class HasManyLoader extends JoinableLoader
27
{
28
    use WhereTrait;
29
30
    /**
31
     * Default set of relation options. Child implementation might defined their of default options.
32
     *
33
     * @var array
34
     */
35
    protected $options = [
36
        'load'      => false,
37
        'constrain' => true,
38
        'method'    => self::POSTLOAD,
39
        'minify'    => true,
40
        'as'        => null,
41
        'using'     => null,
42
        'where'     => null,
43
    ];
44
45
    /**
46
     * {@inheritdoc}
47
     */
48
    public function __construct(ORMInterface $orm, string $name, string $target, array $schema)
49
    {
50
        parent::__construct($orm, $name, $target, $schema);
51
        $this->options['where'] = $schema[Relation::WHERE] ?? [];
52
    }
53
54
    /**
55
     * {@inheritdoc}
56
     */
57
    public function configureQuery(SelectQuery $query, array $outerKeys = []): SelectQuery
58
    {
59
        if ($this->isLoaded() && $this->isJoined() && $query->getLimit() !== 0) {
60
            throw new LoaderException('Unable to load data using join with limit on parent query');
61
        }
62
63
        if (!empty($this->options['using'])) {
64
            // use pre-defined query
65
            return parent::configureQuery($query, $outerKeys);
66
        }
67
68
        $localKey = $this->localKey(Relation::OUTER_KEY);
69
70
        if ($this->isJoined()) {
71
            $query->join(
72
                $this->getJoinMethod(),
73
                $this->getJoinTable()
74
            )->on(
75
                $localKey,
76
                $this->parentKey(Relation::INNER_KEY)
77
            );
78
        } else {
79
            // relation is loaded using external query
80
            $query->where($localKey, 'IN', new Parameter($outerKeys));
81
        }
82
83
        //User specified WHERE conditions
84
        $this->setWhere(
85
            $query,
86
            $this->getAlias(),
87
            $this->isJoined() ? 'onWhere' : 'where',
88
            $this->options['where'] ?? $this->schema[Relation::WHERE] ?? []
89
        );
90
91
        return parent::configureQuery($query);
92
    }
93
94
    /**
95
     * {@inheritdoc}
96
     */
97
    protected function initNode(): AbstractNode
98
    {
99
        $node = new ArrayNode(
100
            $this->columnNames(),
101
            $this->define(Schema::PRIMARY_KEY),
102
            $this->schema[Relation::OUTER_KEY],
103
            $this->schema[Relation::INNER_KEY]
104
        );
105
106
        $typecast = $this->define(Schema::TYPECAST);
107
        if ($typecast !== null) {
108
            $node->setTypecast(new Typecast($typecast, $this->getSource()->getDatabase()));
109
        }
110
111
        return $node;
112
    }
113
}
114