Merge "Validate BlockID cookie before use"
[lhc/web/wiklou.git] / includes / libs / rdbms / database / resultwrapper / ResultWrapper.php
1 <?php
2
3 use Wikimedia\Rdbms\IResultWrapper;
4
5 /**
6 * Result wrapper for grabbing data queried from an IDatabase object
7 *
8 * Note that using the Iterator methods in combination with the non-Iterator
9 * DB result iteration functions may cause rows to be skipped or repeated.
10 *
11 * By default, this will use the iteration methods of the IDatabase handle if provided.
12 * Subclasses can override methods to make it solely work on the result resource instead.
13 * If no database is provided, and the subclass does not override the DB iteration methods,
14 * then a RuntimeException will be thrown when iteration is attempted.
15 *
16 * The result resource field should not be accessed from non-Database related classes.
17 * It is database class specific and is stored here to associate iterators with queries.
18 *
19 * @ingroup Database
20 */
21 class ResultWrapper implements IResultWrapper {
22 /** @var resource|array|null Optional underlying result handle for subclass usage */
23 public $result;
24
25 /** @var IDatabase|null */
26 protected $db;
27
28 /** @var int */
29 protected $pos = 0;
30 /** @var stdClass|null */
31 protected $currentRow = null;
32
33 /**
34 * Create a row iterator from a result resource and an optional Database object
35 *
36 * Only Database-related classes should construct ResultWrapper. Other code may
37 * use the FakeResultWrapper subclass for convenience or compatibility shims, however.
38 *
39 * @param IDatabase|null $db Optional database handle
40 * @param ResultWrapper|array|resource $result Optional underlying result handle
41 */
42 public function __construct( IDatabase $db = null, $result ) {
43 $this->db = $db;
44 if ( $result instanceof ResultWrapper ) {
45 $this->result = $result->result;
46 } else {
47 $this->result = $result;
48 }
49 }
50
51 public function numRows() {
52 return $this->getDB()->numRows( $this );
53 }
54
55 public function fetchObject() {
56 return $this->getDB()->fetchObject( $this );
57 }
58
59 public function fetchRow() {
60 return $this->getDB()->fetchRow( $this );
61 }
62
63 public function seek( $row ) {
64 $this->getDB()->dataSeek( $this, $row );
65 }
66
67 public function free() {
68 if ( $this->db ) {
69 $this->db->freeResult( $this );
70 $this->db = null;
71 }
72 $this->result = null;
73 }
74
75 /**
76 * @return IDatabase
77 * @throws RuntimeException
78 */
79 private function getDB() {
80 if ( !$this->db ) {
81 throw new RuntimeException( get_class( $this ) . ' needs a DB handle for iteration.' );
82 }
83
84 return $this->db;
85 }
86
87 function rewind() {
88 if ( $this->numRows() ) {
89 $this->getDB()->dataSeek( $this, 0 );
90 }
91 $this->pos = 0;
92 $this->currentRow = null;
93 }
94
95 function current() {
96 if ( is_null( $this->currentRow ) ) {
97 $this->next();
98 }
99
100 return $this->currentRow;
101 }
102
103 function key() {
104 return $this->pos;
105 }
106
107 function next() {
108 $this->pos++;
109 $this->currentRow = $this->fetchObject();
110
111 return $this->currentRow;
112 }
113
114 function valid() {
115 return $this->current() !== false;
116 }
117 }