Start splitting back-end functions from the Article user-interface class.
[lhc/web/wiklou.git] / includes / Revision.php
1 <?php
2
3 require_once( 'Database.php' );
4 require_once( 'Article.php' );
5
6 class Revision {
7 /**
8 * Load a page revision from a given revision ID number.
9 * Returns null if no such revision can be found.
10 *
11 * @param int $id
12 * @static
13 * @access public
14 */
15 function &newFromId( $id ) {
16 return Revision::newFromConds(
17 array( 'page_id=rev_page',
18 'rev_id' => IntVal( $id ),
19 'rev_id=old_id' ) );
20 }
21
22 /**
23 * Load either the current, or a specified, revision
24 * that's attached to a given title. If not attached
25 * to that title, will return null.
26 *
27 * @param Title $title
28 * @param int $id
29 * @return Revision
30 * @access public
31 */
32 function &newFromTitle( &$title, $id = 0 ) {
33 if( $id ) {
34 $matchId = IntVal( $id );
35 } else {
36 $matchId = 'page_latest';
37 }
38 return Revision::newFromConds(
39 array( "rev_id=$matchId",
40 'page_id=rev_page',
41 'page_namespace' => $title->getNamespace(),
42 'page_title' => $title->getDbkey(),
43 'rev_id=old_id' ) );
44 }
45
46 /**
47 * Given a set of conditions, fetch a revision.
48 *
49 * @param array $conditions
50 * @return Revision
51 * @static
52 * @access private
53 */
54 function &newFromConds( $conditions ) {
55 $res =& Revision::fetchFromConds( $conditions );
56 if( $res ) {
57 $row = $res->fetchObject();
58 $res->free();
59 if( $row ) {
60 return new Revision( $row );
61 }
62 }
63 return null;
64 }
65
66 /**
67 * Return a wrapper for a series of database rows to
68 * fetch all of a given page's revisions in turn.
69 * Each row can be fed to the constructor to get objects.
70 *
71 * @param Title $title
72 * @return ResultWrapper
73 * @static
74 * @access public
75 */
76 function &fetchAllRevisions( &$title ) {
77 return Revision::fetchFromConds(
78 array( 'page_namespace' => $title->getNamespace(),
79 'page_title' => $title->getDbkey(),
80 'page_id=rev_page',
81 'rev_id=old_id' ) );
82 }
83
84 /**
85 * Return a wrapper for a series of database rows to
86 * fetch all of a given page's revisions in turn.
87 * Each row can be fed to the constructor to get objects.
88 *
89 * @param Title $title
90 * @return ResultWrapper
91 * @static
92 * @access public
93 */
94 function &fetchRevision( &$title ) {
95 return Revision::fetchFromConds(
96 array( 'rev_id=page_latest',
97 'page_namespace' => $title->getNamespace(),
98 'page_title' => $title->getDbkey(),
99 'page_id=rev_page',
100 'rev_id=old_id' ) );
101 }
102 /**
103 * Given a set of conditions, return a ResultWrapper
104 * which will return matching database rows with the
105 * fields necessary to build Revision objects.
106 *
107 * @param array $conditions
108 * @return ResultWrapper
109 * @static
110 * @access private
111 */
112 function &fetchFromConds( $conditions ) {
113 $dbr =& wfGetDB( DB_SLAVE );
114 $res = $dbr->select(
115 array( 'page', 'revision', 'text' ),
116 array( 'page_namespace',
117 'page_title',
118 'page_latest',
119 'rev_id',
120 'rev_page',
121 'rev_comment',
122 'rev_user_text',
123 'rev_user',
124 'rev_minor_edit',
125 'rev_timestamp',
126 'old_flags',
127 'old_text' ),
128 $conditions,
129 'Revision::fetchRow' );
130 return $dbr->resultObject( $res );
131 }
132
133 /**
134 * @param object $row
135 * @access private
136 */
137 function Revision( $row ) {
138 $this->mId = IntVal( $row->rev_id );
139 $this->mPage = IntVal( $row->rev_page );
140 $this->mComment = $row->rev_comment;
141 $this->mUserText = $row->rev_user_text;
142 $this->mUser = IntVal( $row->rev_user );
143 $this->mMinorEdit = IntVal( $row->rev_minor_edit );
144 $this->mTimestamp = $row->rev_timestamp;
145
146 $this->mCurrent = ( $row->rev_id == $row->page_latest );
147 $this->mTitle = Title::makeTitle( $row->page_namespace,
148 $row->page_title );
149 $this->mText = $this->getRevisionText( $row );
150 }
151
152 /** @+
153 * @access public
154 */
155
156 /**
157 * @return int
158 */
159 function getId() {
160 return $this->mId;
161 }
162
163 /**
164 * Returns the title of the page associated with this entry.
165 * @return Title
166 */
167 function &getTitle() {
168 if( isset( $this->mTitle ) ) {
169 return $this->mTitle;
170 }
171 $dbr =& wfGetDB( DB_SLAVE );
172 $row = $dbr->selectRow(
173 array( 'page', 'revision' ),
174 array( 'page_namespace', 'page_title' ),
175 array( 'page_id=rev_page',
176 'rev_id' => $this->mId ),
177 'Revision::getTItle' );
178 if( $row ) {
179 $this->mTitle =& Title::makeTitle( $row->page_namespace,
180 $row->page_title );
181 }
182 return $this->mTitle;
183 }
184
185 /**
186 * @return int
187 */
188 function getUser() {
189 return $this->mUser;
190 }
191
192 /**
193 * @return string
194 */
195 function getUserText() {
196 return $this->mUserText;
197 }
198
199 /**
200 * @return string
201 */
202 function getComment() {
203 return $this->mComment;
204 }
205
206 /**
207 * @return bool
208 */
209 function isMinor() {
210 return (bool)$this->mMinorEdit;
211 }
212
213 /**
214 * @return string
215 */
216 function getText() {
217 return $this->mText;
218 }
219
220 /**
221 * @return string
222 */
223 function getTimestamp() {
224 return $this->mTimestamp;
225 }
226
227 /**
228 * @return bool
229 */
230 function isCurrent() {
231 return $this->mCurrent;
232 }
233
234 /**
235 * @return Revision
236 */
237 function &getPrevious() {
238 $prev = $this->mTitle->getPreviousRevisionID( $this->mId );
239 return Revision::newFromTitle( $this->mTitle, $prev );
240 }
241
242 /**
243 * @return Revision
244 */
245 function &getNext() {
246 $next = $this->mTitle->getNextRevisionID( $this->mId );
247 return Revision::newFromTitle( $this->mTitle, $next );
248 }
249 /** @- */
250
251 /**
252 * Get revision text associated with an old or archive row
253 * $row is usually an object from wfFetchRow(), both the flags and the text
254 * field must be included
255 * @static
256 * @param integer $row Id of a row
257 * @param string $prefix table prefix (default 'old_')
258 * @return string $text|false the text requested
259 */
260 function getRevisionText( $row, $prefix = 'old_' ) {
261 $fname = 'Revision::getRevisionText';
262 wfProfileIn( $fname );
263
264 # Get data
265 $textField = $prefix . 'text';
266 $flagsField = $prefix . 'flags';
267
268 if( isset( $row->$flagsField ) ) {
269 $flags = explode( ',', $row->$flagsField );
270 } else {
271 $flags = array();
272 }
273
274 if( isset( $row->$textField ) ) {
275 $text = $row->$textField;
276 } else {
277 wfProfileOut( $fname );
278 return false;
279 }
280
281 if( in_array( 'gzip', $flags ) ) {
282 # Deal with optional compression of archived pages.
283 # This can be done periodically via maintenance/compressOld.php, and
284 # as pages are saved if $wgCompressRevisions is set.
285 $text = gzinflate( $text );
286 }
287
288 if( in_array( 'object', $flags ) ) {
289 # Generic compressed storage
290 $obj = unserialize( $text );
291
292 # Bugger, corrupted my test database by double-serializing
293 if ( !is_object( $obj ) ) {
294 $obj = unserialize( $obj );
295 }
296
297 $text = $obj->getText();
298 }
299
300 global $wgLegacyEncoding;
301 if( $wgLegacyEncoding && !in_array( 'utf-8', $flags ) ) {
302 # Old revisions kept around in a legacy encoding?
303 # Upconvert on demand.
304 global $wgInputEncoding, $wgContLang;
305 $text = $wgContLang->iconv( $wgLegacyEncoding, $wgInputEncoding, $text );
306 }
307 wfProfileOut( $fname );
308 return $text;
309 }
310
311 /**
312 * If $wgCompressRevisions is enabled, we will compress data.
313 * The input string is modified in place.
314 * Return value is the flags field: contains 'gzip' if the
315 * data is compressed, and 'utf-8' if we're saving in UTF-8
316 * mode.
317 *
318 * @static
319 * @param mixed $text reference to a text
320 * @return string
321 */
322 function compressRevisionText( &$text ) {
323 global $wgCompressRevisions, $wgUseLatin1;
324 $flags = array();
325 if( !$wgUseLatin1 ) {
326 # Revisions not marked this way will be converted
327 # on load if $wgLegacyCharset is set in the future.
328 $flags[] = 'utf-8';
329 }
330 if( $wgCompressRevisions ) {
331 if( function_exists( 'gzdeflate' ) ) {
332 $text = gzdeflate( $text );
333 $flags[] = 'gzip';
334 } else {
335 wfDebug( "Revision::compressRevisionText() -- no zlib support, not compressing\n" );
336 }
337 }
338 return implode( ',', $flags );
339 }
340
341
342 }
343
344
345 ?>