Issues (291)

src/PageIterator.php (2 issues)

1
<?php
2
3
declare(strict_types=1);
4
5
namespace TheCodingMachine\TDBM;
6
7
use Doctrine\DBAL\Statement;
8
use Mouf\Database\MagicQuery;
9
use Psr\Log\LoggerInterface;
10
use Psr\Log\NullLogger;
11
12
/*
13
 Copyright (C) 2006-2017 David Négrier - THE CODING MACHINE
14
15
 This program is free software; you can redistribute it and/or modify
16
 it under the terms of the GNU General Public License as published by
17
 the Free Software Foundation; either version 2 of the License, or
18
 (at your option) any later version.
19
20
 This program is distributed in the hope that it will be useful,
21
 but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
 GNU General Public License for more details.
24
25
 You should have received a copy of the GNU General Public License
26
 along with this program; if not, write to the Free Software
27
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
28
 */
29
30
/**
31
 * Iterator used to retrieve results.
32
 */
33
class PageIterator implements PageInterface, \ArrayAccess, \JsonSerializable
34
{
35
    /** @var Statement */
36
    protected $statement;
37
38
    /** @var bool */
39
    protected $fetchStarted = false;
40
    /** @var ObjectStorageInterface */
41
    private $objectStorage;
42
    /** @var string|null */
43
    private $className;
44
45
    /** @var ResultIterator */
46
    private $parentResult;
47
    /** @var TDBMService */
48
    private $tdbmService;
49
    /** @var string */
50
    private $magicSql;
51
    /** @var mixed[] */
52
    private $parameters;
53
    /** @var int|null */
54
    private $limit;
55
    /** @var int|null */
56
    private $offset;
57
    /** @var array[] */
58
    private $columnDescriptors;
59
    /** @var MagicQuery */
60
    private $magicQuery;
61
62
    /**
63
     * The key of the current retrieved object.
64
     *
65
     * @var int
66
     */
67
    protected $key = -1;
68
69
    /** @var AbstractTDBMObject|null */
70
    protected $current;
71
72
    /** @var InnerResultIteratorInterface */
73
    private $innerResultIterator;
74
75
    /** @var int */
76
    private $mode;
77
78
    /** @var LoggerInterface */
79
    private $logger;
80
81
    private function __construct()
82
    {
83
    }
84
85
    /**
86
     * @param mixed[] $parameters
87
     * @param array[] $columnDescriptors
88
     */
89
    public static function createResultIterator(ResultIterator $parentResult, string $magicSql, array $parameters, int $limit, int $offset, array $columnDescriptors, ObjectStorageInterface $objectStorage, ?string $className, TDBMService $tdbmService, MagicQuery $magicQuery, int $mode, LoggerInterface $logger): self
90
    {
91
        $iterator = new self();
92
        $iterator->parentResult = $parentResult;
93
        $iterator->magicSql = $magicSql;
94
        $iterator->objectStorage = $objectStorage;
95
        $iterator->className = $className;
96
        $iterator->tdbmService = $tdbmService;
97
        $iterator->parameters = $parameters;
98
        $iterator->limit = $limit;
99
        $iterator->offset = $offset;
100
        $iterator->columnDescriptors = $columnDescriptors;
101
        $iterator->magicQuery = $magicQuery;
102
        $iterator->mode = $mode;
103
        $iterator->logger = $logger;
104
        return $iterator;
105
    }
106
107
    public static function createEmpyIterator(ResultIterator $parentResult): self
108
    {
109
        $iterator = new self();
110
        $iterator->parentResult = $parentResult;
111
        $iterator->logger = new NullLogger();
112
        return $iterator;
113
    }
114
115
    /**
116
     * Retrieve an external iterator.
117
     *
118
     * @return InnerResultIteratorInterface
119
     */
120
    public function getIterator(): \Traversable
121
    {
122
        if ($this->innerResultIterator === null) {
123
            if ($this->parentResult->count() === 0) {
124
                $this->innerResultIterator = new EmptyInnerResultIterator();
125
            } elseif ($this->mode === TDBMService::MODE_CURSOR) {
126
                $this->innerResultIterator = InnerResultIterator::createInnerResultIterator($this->magicSql, $this->parameters, $this->limit, $this->offset, $this->columnDescriptors, $this->objectStorage, $this->className, $this->tdbmService, $this->magicQuery, $this->logger);
127
            } else {
128
                $this->innerResultIterator = InnerResultArray::createInnerResultIterator($this->magicSql, $this->parameters, $this->limit, $this->offset, $this->columnDescriptors, $this->objectStorage, $this->className, $this->tdbmService, $this->magicQuery, $this->logger);
129
            }
130
        }
131
132
        return $this->innerResultIterator;
133
    }
134
135
    public function getCurrentOffset(): int
136
    {
137
        return $this->offset;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->offset could return the type null which is incompatible with the type-hinted return integer. Consider adding an additional type-check to rule them out.
Loading history...
138
    }
139
140
    public function getCurrentPage(): int
141
    {
142
        return (int) floor($this->offset / $this->limit) + 1;
143
    }
144
145
    public function getCurrentLimit(): int
146
    {
147
        return $this->limit;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->limit could return the type null which is incompatible with the type-hinted return integer. Consider adding an additional type-check to rule them out.
Loading history...
148
    }
149
150
    /**
151
     * Return the number of results on the current page of the {@link Result}.
152
     */
153
    public function count(): int
154
    {
155
        return $this->getIterator()->count();
156
    }
157
158
    /**
159
     * Return the number of ALL results in the paginatable of {@link Result}.
160
     */
161
    public function totalCount(): int
162
    {
163
        return $this->parentResult->count();
164
    }
165
166
    /**
167
     * Casts the result set to a PHP array.
168
     *
169
     * @return AbstractTDBMObject[]
170
     */
171
    public function toArray(): array
172
    {
173
        return iterator_to_array($this->getIterator());
174
    }
175
176
    /**
177
     * Returns a new iterator mapping any call using the $callable function.
178
     *
179
     * @param callable $callable
180
     *
181
     * @return MapIterator
182
     */
183
    public function map(callable $callable): MapIterator
184
    {
185
        if ($this->count() === 0) {
186
            return new MapIterator([], $callable);
187
        }
188
        return new MapIterator($this->getIterator(), $callable);
189
    }
190
191
    /**
192
     * Whether a offset exists.
193
     *
194
     * @link http://php.net/manual/en/arrayaccess.offsetexists.php
195
     *
196
     * @param mixed $offset <p>
197
     *                      An offset to check for.
198
     *                      </p>
199
     *
200
     * @return bool true on success or false on failure.
201
     *              </p>
202
     *              <p>
203
     *              The return value will be casted to boolean if non-boolean was returned
204
     *
205
     * @since 5.0.0
206
     */
207
    public function offsetExists($offset): bool
208
    {
209
        return $this->getIterator()->offsetExists($offset);
210
    }
211
212
    /**
213
     * Offset to retrieve.
214
     *
215
     * @link http://php.net/manual/en/arrayaccess.offsetget.php
216
     *
217
     * @param mixed $offset <p>
218
     *                      The offset to retrieve.
219
     *                      </p>
220
     *
221
     * @return mixed Can return all value types
222
     *
223
     * @since 5.0.0
224
     */
225
    public function offsetGet($offset): mixed
226
    {
227
        return $this->getIterator()->offsetGet($offset);
228
    }
229
230
    /**
231
     * Offset to set.
232
     *
233
     * @link http://php.net/manual/en/arrayaccess.offsetset.php
234
     *
235
     * @param mixed $offset <p>
236
     *                      The offset to assign the value to.
237
     *                      </p>
238
     * @param mixed $value  <p>
239
     *                      The value to set.
240
     *                      </p>
241
     *
242
     * @since 5.0.0
243
     */
244
    public function offsetSet($offset, $value): void
245
    {
246
        $this->getIterator()->offsetSet($offset, $value);
247
    }
248
249
    /**
250
     * Offset to unset.
251
     *
252
     * @link http://php.net/manual/en/arrayaccess.offsetunset.php
253
     *
254
     * @param mixed $offset <p>
255
     *                      The offset to unset.
256
     *                      </p>
257
     *
258
     * @since 5.0.0
259
     */
260
    public function offsetUnset($offset): void
261
    {
262
        $this->getIterator()->offsetUnset($offset);
263
    }
264
265
    /**
266
     * Specify data which should be serialized to JSON.
267
     *
268
     * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
269
     *
270
     * @return mixed data which can be serialized by <b>json_encode</b>,
271
     *               which is a value of any type other than a resource
272
     *
273
     * @since 5.4.0
274
     */
275
    public function jsonSerialize(): mixed
276
    {
277
        return array_map(function (AbstractTDBMObject $item) {
278
            return $item->jsonSerialize();
279
        }, $this->toArray());
280
    }
281
}
282