Merge "Group E-mail settings stuff in Setup.php"
[lhc/web/wiklou.git] / includes / db / DatabaseUtility.php
1 <?php
2 /**
3 * This file contains database-related utility classes.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * http://www.gnu.org/copyleft/gpl.html
19 *
20 * @file
21 * @ingroup Database
22 */
23
24 /**
25 * Utility class.
26 * @ingroup Database
27 */
28 class DBObject {
29 public $mData;
30
31 function __construct( $data ) {
32 $this->mData = $data;
33 }
34
35 /**
36 * @return bool
37 */
38 function isLOB() {
39 return false;
40 }
41
42 function data() {
43 return $this->mData;
44 }
45 }
46
47 /**
48 * Utility class
49 * @ingroup Database
50 *
51 * This allows us to distinguish a blob from a normal string and an array of strings
52 */
53 class Blob {
54 /** @var string */
55 protected $mData;
56
57 function __construct( $data ) {
58 $this->mData = $data;
59 }
60
61 function fetch() {
62 return $this->mData;
63 }
64 }
65
66 /**
67 * Base for all database-specific classes representing information about database fields
68 * @ingroup Database
69 */
70 interface Field {
71 /**
72 * Field name
73 * @return string
74 */
75 function name();
76
77 /**
78 * Name of table this field belongs to
79 * @return string
80 */
81 function tableName();
82
83 /**
84 * Database type
85 * @return string
86 */
87 function type();
88
89 /**
90 * Whether this field can store NULL values
91 * @return bool
92 */
93 function isNullable();
94 }
95
96 /**
97 * Result wrapper for grabbing data queried by someone else
98 * @ingroup Database
99 */
100 class ResultWrapper implements Iterator {
101 /** @var resource */
102 public $result;
103
104 /** @var DatabaseBase */
105 protected $db;
106
107 /** @var int */
108 protected $pos = 0;
109
110 /** @var object|null */
111 protected $currentRow = null;
112
113 /**
114 * Create a new result object from a result resource and a Database object
115 *
116 * @param DatabaseBase $database
117 * @param resource|ResultWrapper $result
118 */
119 function __construct( $database, $result ) {
120 $this->db = $database;
121
122 if ( $result instanceof ResultWrapper ) {
123 $this->result = $result->result;
124 } else {
125 $this->result = $result;
126 }
127 }
128
129 /**
130 * Get the number of rows in a result object
131 *
132 * @return int
133 */
134 function numRows() {
135 return $this->db->numRows( $this );
136 }
137
138 /**
139 * Fetch the next row from the given result object, in object form.
140 * Fields can be retrieved with $row->fieldname, with fields acting like
141 * member variables.
142 *
143 * @return stdClass
144 * @throws DBUnexpectedError Thrown if the database returns an error
145 */
146 function fetchObject() {
147 return $this->db->fetchObject( $this );
148 }
149
150 /**
151 * Fetch the next row from the given result object, in associative array
152 * form. Fields are retrieved with $row['fieldname'].
153 *
154 * @return array
155 * @throws DBUnexpectedError Thrown if the database returns an error
156 */
157 function fetchRow() {
158 return $this->db->fetchRow( $this );
159 }
160
161 /**
162 * Free a result object
163 */
164 function free() {
165 $this->db->freeResult( $this );
166 unset( $this->result );
167 unset( $this->db );
168 }
169
170 /**
171 * Change the position of the cursor in a result object.
172 * See mysql_data_seek()
173 *
174 * @param int $row
175 */
176 function seek( $row ) {
177 $this->db->dataSeek( $this, $row );
178 }
179
180 /*
181 * ======= Iterator functions =======
182 * Note that using these in combination with the non-iterator functions
183 * above may cause rows to be skipped or repeated.
184 */
185
186 function rewind() {
187 if ( $this->numRows() ) {
188 $this->db->dataSeek( $this, 0 );
189 }
190 $this->pos = 0;
191 $this->currentRow = null;
192 }
193
194 /**
195 * @return stdClass|array|bool
196 */
197 function current() {
198 if ( is_null( $this->currentRow ) ) {
199 $this->next();
200 }
201
202 return $this->currentRow;
203 }
204
205 /**
206 * @return int
207 */
208 function key() {
209 return $this->pos;
210 }
211
212 /**
213 * @return stdClass
214 */
215 function next() {
216 $this->pos++;
217 $this->currentRow = $this->fetchObject();
218
219 return $this->currentRow;
220 }
221
222 /**
223 * @return bool
224 */
225 function valid() {
226 return $this->current() !== false;
227 }
228 }
229
230 /**
231 * Overloads the relevant methods of the real ResultsWrapper so it
232 * doesn't go anywhere near an actual database.
233 */
234 class FakeResultWrapper extends ResultWrapper {
235 /** @var array */
236 public $result = array();
237
238 /** @var null And it's going to stay that way :D */
239 protected $db = null;
240
241 /** @var int */
242 protected $pos = 0;
243
244 /** @var array|stdClass|bool */
245 protected $currentRow = null;
246
247 function __construct( $array ) {
248 $this->result = $array;
249 }
250
251 /**
252 * @return int
253 */
254 function numRows() {
255 return count( $this->result );
256 }
257
258 /**
259 * @return array|bool
260 */
261 function fetchRow() {
262 if ( $this->pos < count( $this->result ) ) {
263 $this->currentRow = $this->result[$this->pos];
264 } else {
265 $this->currentRow = false;
266 }
267 $this->pos++;
268 if ( is_object( $this->currentRow ) ) {
269 return get_object_vars( $this->currentRow );
270 } else {
271 return $this->currentRow;
272 }
273 }
274
275 function seek( $row ) {
276 $this->pos = $row;
277 }
278
279 function free() {
280 }
281
282 /**
283 * Callers want to be able to access fields with $this->fieldName
284 * @return bool|stdClass
285 */
286 function fetchObject() {
287 $this->fetchRow();
288 if ( $this->currentRow ) {
289 return (object)$this->currentRow;
290 } else {
291 return false;
292 }
293 }
294
295 function rewind() {
296 $this->pos = 0;
297 $this->currentRow = null;
298 }
299
300 /**
301 * @return bool|stdClass
302 */
303 function next() {
304 return $this->fetchObject();
305 }
306 }
307
308 /**
309 * Used by DatabaseBase::buildLike() to represent characters that have special
310 * meaning in SQL LIKE clauses and thus need no escaping. Don't instantiate it
311 * manually, use DatabaseBase::anyChar() and anyString() instead.
312 */
313 class LikeMatch {
314 /** @var string */
315 private $str;
316
317 /**
318 * Store a string into a LikeMatch marker object.
319 *
320 * @param string $s
321 */
322 public function __construct( $s ) {
323 $this->str = $s;
324 }
325
326 /**
327 * Return the original stored string.
328 *
329 * @return string
330 */
331 public function toString() {
332 return $this->str;
333 }
334 }
335
336 /**
337 * An object representing a master or slave position in a replicated setup.
338 *
339 * The implementation details of this opaque type are up to the database subclass.
340 */
341 interface DBMasterPos {
342 }