Passed
Pull Request — master (#239)
by
unknown
03:30
created

HasManyLoader::isDataDuplicationPossible()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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