Completed
Branch master (19da56)
by Adrian
01:49
created

Query::chunk()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 0
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 2
rs 10
1
<?php
2
declare(strict_types=1);
3
4
namespace Sirius\Orm;
5
6
use Sirius\Orm\Collection\Collection;
7
use Sirius\Orm\Collection\PaginatedCollection;
8
use Sirius\Sql\Bindings;
9
use Sirius\Sql\Select;
10
11
class Query extends Select
12
{
13
14
    /**
15
     * @var Orm
16
     */
17
    protected $orm;
18
19
    /**
20
     * @var Mapper
21
     */
22
    protected $mapper;
23
24
    /**
25
     * @var array
26
     */
27
    protected $load = [];
28
29
    /**
30
     * @var array
31
     */
32
    protected $guards = [];
33
34
    /**
35
     * @var array
36
     */
37
    protected $scopes = [];
38
39
    public function __construct(Mapper $mapper, Bindings $bindings = null, string $indent = '')
40
    {
41
        parent::__construct($mapper->getReadConnection(), $bindings, $indent);
42
        $this->mapper = $mapper;
43
        $this->from($this->mapper->getTableReference());
44
        $this->resetColumns();
45
        $this->columns($this->mapper->getTableAlias(true) . '.*');
46
    }
47
48
    public function __call(string $method, array $params)
49
    {
50
        $scope = $this->mapper->getQueryScope($method);
51
        if ($scope && is_callable($scope)) {
52
            return $scope($this, ...$params);
53
        }
54
55
        return parent::__call($method, $params);
56
    }
57
58
    public function __clone()
59
    {
60
        $vars = get_object_vars($this);
61
        unset($vars['mapper']);
62
        foreach ($vars as $name => $prop) {
63
            if (is_object($prop)) {
64
                $this->$name = clone $prop;
65
            }
66
        }
67
    }
68
69
70
    public function load(...$relations): self
71
    {
72
        foreach ($relations as $relation) {
73
            if (is_array($relation)) {
74
                $name = key($relation);
75
                $callback = current($relation);
76
            } else {
77
                $name = $relation;
78
                $callback = null;
79
            }
80
            $this->load[$name] = $callback;
81
        }
82
83
        return $this;
84
    }
85
86
    public function joinWith($name): Query
87
    {
88
        if (! $this->mapper->hasRelation($name)) {
89
            throw new \InvalidArgumentException(
90
                sprintf("Relation %s, not defined for %s", $name, $this->mapper->getTable())
91
            );
92
        }
93
        $relation = $this->mapper->getRelation($name);
94
95
        return $relation->joinSubselect($this, $name);
96
    }
97
98
    public function subSelectForJoinWith(): Query
99
    {
100
        $subselect = new Query($this->mapper, $this->bindings, $this->indent . '    ');
101
        $subselect->resetFrom();
102
        $subselect->resetColumns();
103
104
        return $subselect;
105
    }
106
107
    public function first()
108
    {
109
        $row = $this->fetchOne();
110
111
        return $this->mapper->newEntityFromRow($row, $this->load);
112
    }
113
114
    public function get(): Collection
115
    {
116
        return $this->mapper->newCollectionFromRows(
117
            $this->connection->fetchAll($this->getStatement(), $this->getBindValues()),
118
            $this->load
119
        );
120
    }
121
122
    public function paginate($perPage, $page): PaginatedCollection
123
    {
124
        /** @var Query $countQuery */
125
        $countQuery = clone $this;
126
        $total      = $countQuery->count();
127
128
        if ($total == 0) {
129
            $this->mapper->newPaginatedCollectionFromRows([], $total, $perPage, $page, $this->load);
130
        }
131
132
        $this->perPage($perPage);
133
        $this->page($page);
134
135
        return $this->mapper->newPaginatedCollectionFromRows($this->fetchAll(), $total, $perPage, $page, $this->load);
136
    }
137
138
    /**
139
     * @todo implement this feature
140
     */
141
    /*public function chunk($count, $callback)
142
    {
143
    }*/
144
145
    public function count()
146
    {
147
        $this->resetOrderBy();
148
        $this->resetColumns();
149
        $this->columns('COUNT(*) AS total');
150
151
        return (int)$this->fetchValue();
152
    }
153
154
    public function setGuards(array $guards)
155
    {
156
        foreach ($guards as $column => $value) {
157
            if (is_int($column)) {
158
                $this->guards[] = $value;
159
            } else {
160
                $this->guards[$column] = $value;
161
            }
162
        }
163
164
        return $this;
165
    }
166
167
    public function resetGuards()
168
    {
169
        $this->guards = [];
170
171
        return;
172
    }
173
174
    protected function applyGuards()
175
    {
176
        if (empty($this->guards)) {
177
            return;
178
        }
179
180
        $this->groupCurrentWhere();
181
        foreach ($this->guards as $column => $value) {
182
            if (is_int($column)) {
183
                $this->where($value);
184
            } else {
185
                $this->where($column, $value);
186
            }
187
        }
188
    }
189
190
    public function getStatement(): string
191
    {
192
        $this->applyGuards();
193
194
        return parent::getStatement();
195
    }
196
}
197