GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Issues (910)

framework/db/BatchQueryResult.php (1 issue)

1
<?php
2
/**
3
 * @link https://www.yiiframework.com/
4
 * @copyright Copyright (c) 2008 Yii Software LLC
5
 * @license https://www.yiiframework.com/license/
6
 */
7
8
namespace yii\db;
9
10
use yii\base\Component;
11
12
/**
13
 * BatchQueryResult represents a batch query from which you can retrieve data in batches.
14
 *
15
 * You usually do not instantiate BatchQueryResult directly. Instead, you obtain it by
16
 * calling [[Query::batch()]] or [[Query::each()]]. Because BatchQueryResult implements the [[\Iterator]] interface,
17
 * you can iterate it to obtain a batch of data in each iteration. For example,
18
 *
19
 * ```php
20
 * $query = (new Query)->from('user');
21
 * foreach ($query->batch() as $i => $users) {
22
 *     // $users represents the rows in the $i-th batch
23
 * }
24
 * foreach ($query->each() as $user) {
25
 * }
26
 * ```
27
 *
28
 * @author Qiang Xue <[email protected]>
29
 * @since 2.0
30
 */
31
class BatchQueryResult extends Component implements \Iterator
32
{
33
    /**
34
     * @event Event an event that is triggered when the batch query is reset.
35
     * @see reset()
36
     * @since 2.0.41
37
     */
38
    const EVENT_RESET = 'reset';
39
    /**
40
     * @event Event an event that is triggered when the last batch has been fetched.
41
     * @since 2.0.41
42
     */
43
    const EVENT_FINISH = 'finish';
44
    /**
45
     * MSSQL error code for exception that is thrown when last batch is size less than specified batch size
46
     * @see https://github.com/yiisoft/yii2/issues/10023
47
     */
48
    const MSSQL_NO_MORE_ROWS_ERROR_CODE = -13;
49
50
    /**
51
     * @var Connection|null the DB connection to be used when performing batch query.
52
     * If null, the "db" application component will be used.
53
     */
54
    public $db;
55
    /**
56
     * @var Query the query object associated with this batch query.
57
     * Do not modify this property directly unless after [[reset()]] is called explicitly.
58
     */
59
    public $query;
60
    /**
61
     * @var int the number of rows to be returned in each batch.
62
     */
63
    public $batchSize = 100;
64
    /**
65
     * @var bool whether to return a single row during each iteration.
66
     * If false, a whole batch of rows will be returned in each iteration.
67
     */
68
    public $each = false;
69
70
    /**
71
     * @var DataReader the data reader associated with this batch query.
72
     */
73
    private $_dataReader;
74
    /**
75
     * @var array the data retrieved in the current batch
76
     */
77
    private $_batch;
78
    /**
79
     * @var mixed the value for the current iteration
80
     */
81
    private $_value;
82
    /**
83
     * @var string|int the key for the current iteration
84
     */
85
    private $_key;
86
87
88
    /**
89
     * Destructor.
90
     */
91 12
    public function __destruct()
92
    {
93
        // make sure cursor is closed
94 12
        $this->reset();
95
    }
96
97
    /**
98
     * Resets the batch query.
99
     * This method will clean up the existing batch query so that a new batch query can be performed.
100
     */
101 12
    public function reset()
102
    {
103 12
        if ($this->_dataReader !== null) {
104 12
            $this->_dataReader->close();
105
        }
106 12
        $this->_dataReader = null;
107 12
        $this->_batch = null;
108 12
        $this->_value = null;
109 12
        $this->_key = null;
110 12
        $this->trigger(self::EVENT_RESET);
111
    }
112
113
    /**
114
     * Resets the iterator to the initial state.
115
     * This method is required by the interface [[\Iterator]].
116
     */
117 12
    #[\ReturnTypeWillChange]
118
    public function rewind()
119
    {
120 12
        $this->reset();
121 12
        $this->next();
122
    }
123
124
    /**
125
     * Moves the internal pointer to the next dataset.
126
     * This method is required by the interface [[\Iterator]].
127
     */
128 12
    #[\ReturnTypeWillChange]
129
    public function next()
130
    {
131 12
        if ($this->_batch === null || !$this->each || $this->each && next($this->_batch) === false) {
132 12
            $this->_batch = $this->fetchData();
133 12
            reset($this->_batch);
134
        }
135
136 12
        if ($this->each) {
137 3
            $this->_value = current($this->_batch);
138 3
            if ($this->query->indexBy !== null) {
139 3
                $this->_key = key($this->_batch);
140 3
            } elseif (key($this->_batch) !== null) {
141 3
                $this->_key = $this->_key === null ? 0 : $this->_key + 1;
142
            } else {
143 3
                $this->_key = null;
144
            }
145
        } else {
146 12
            $this->_value = $this->_batch;
147 12
            $this->_key = $this->_key === null ? 0 : $this->_key + 1;
148
        }
149
    }
150
151
    /**
152
     * Fetches the next batch of data.
153
     * @return array the data fetched
154
     * @throws Exception
155
     */
156 12
    protected function fetchData()
157
    {
158 12
        if ($this->_dataReader === null) {
159 12
            $this->_dataReader = $this->query->createCommand($this->db)->query();
160
        }
161
162 12
        $rows = $this->getRows();
163
164 12
        return $this->query->populate($rows);
165
    }
166
167
    /**
168
     * Reads and collects rows for batch
169
     * @return array
170
     * @since 2.0.23
171
     */
172 12
    protected function getRows()
173
    {
174 12
        $rows = [];
175 12
        $count = 0;
176
177
        try {
178 12
            while ($count++ < $this->batchSize) {
179 12
                if ($row = $this->_dataReader->read()) {
180 12
                    $rows[] = $row;
181
                } else {
182
                    // we've reached the end
183 12
                    $this->trigger(self::EVENT_FINISH);
184 12
                    break;
185
                }
186
            }
187
        } catch (\PDOException $e) {
188
            $errorCode = isset($e->errorInfo[1]) ? $e->errorInfo[1] : null;
189
            if ($this->getDbDriverName() !== 'sqlsrv' || $errorCode !== self::MSSQL_NO_MORE_ROWS_ERROR_CODE) {
190
                throw $e;
191
            }
192
        }
193
194 12
        return $rows;
195
    }
196
197
    /**
198
     * Returns the index of the current dataset.
199
     * This method is required by the interface [[\Iterator]].
200
     * @return int the index of the current row.
201
     */
202 3
    #[\ReturnTypeWillChange]
203
    public function key()
204
    {
205 3
        return $this->_key;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->_key also could return the type string which is incompatible with the documented return type integer.
Loading history...
206
    }
207
208
    /**
209
     * Returns the current dataset.
210
     * This method is required by the interface [[\Iterator]].
211
     * @return mixed the current dataset.
212
     */
213 12
    #[\ReturnTypeWillChange]
214
    public function current()
215
    {
216 12
        return $this->_value;
217
    }
218
219
    /**
220
     * Returns whether there is a valid dataset at the current position.
221
     * This method is required by the interface [[\Iterator]].
222
     * @return bool whether there is a valid dataset at the current position.
223
     */
224 12
    #[\ReturnTypeWillChange]
225
    public function valid()
226
    {
227 12
        return !empty($this->_batch);
228
    }
229
230
    /**
231
     * Gets db driver name from the db connection that is passed to the `batch()`, if it is not passed it uses
232
     * connection from the active record model
233
     * @return string|null
234
     */
235
    private function getDbDriverName()
236
    {
237
        if (isset($this->db->driverName)) {
238
            return $this->db->driverName;
239
        }
240
241
        if (!empty($this->_batch)) {
242
            $key = array_keys($this->_batch)[0];
243
            if (isset($this->_batch[$key]->db->driverName)) {
244
                return $this->_batch[$key]->db->driverName;
245
            }
246
        }
247
248
        return null;
249
    }
250
251
    /**
252
     * Unserialization is disabled to prevent remote code execution in case application
253
     * calls unserialize() on user input containing specially crafted string.
254
     * @see https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-15148
255
     * @since 2.0.38
256
     */
257
    public function __wakeup()
258
    {
259
        throw new \BadMethodCallException('Cannot unserialize ' . __CLASS__);
260
    }
261
}
262