* (bug 1723) Article size in history
[lhc/web/wiklou.git] / includes / Revision.php
1 <?php
2 /**
3 * @todo document
4 */
5
6 /**
7 * @todo document
8 */
9 class Revision {
10 const DELETED_TEXT = 1;
11 const DELETED_COMMENT = 2;
12 const DELETED_USER = 4;
13 const DELETED_RESTRICTED = 8;
14 const DELETED_NAME = 16;
15
16 /**
17 * Load a page revision from a given revision ID number.
18 * Returns null if no such revision can be found.
19 *
20 * @param int $id
21 * @access public
22 * @static
23 */
24 public static function newFromId( $id ) {
25 return Revision::newFromConds(
26 array( 'page_id=rev_page',
27 'rev_id' => intval( $id ) ) );
28 }
29
30 /**
31 * Load either the current, or a specified, revision
32 * that's attached to a given title. If not attached
33 * to that title, will return null.
34 *
35 * @param Title $title
36 * @param int $id
37 * @return Revision
38 * @access public
39 * @static
40 */
41 public static function newFromTitle( &$title, $id = 0 ) {
42 if( $id ) {
43 $matchId = intval( $id );
44 } else {
45 $matchId = 'page_latest';
46 }
47 return Revision::newFromConds(
48 array( "rev_id=$matchId",
49 'page_id=rev_page',
50 'page_namespace' => $title->getNamespace(),
51 'page_title' => $title->getDbkey() ) );
52 }
53
54 /**
55 * Load a page revision from a given revision ID number.
56 * Returns null if no such revision can be found.
57 *
58 * @param Database $db
59 * @param int $id
60 * @access public
61 * @static
62 */
63 public static function loadFromId( &$db, $id ) {
64 return Revision::loadFromConds( $db,
65 array( 'page_id=rev_page',
66 'rev_id' => intval( $id ) ) );
67 }
68
69 /**
70 * Load either the current, or a specified, revision
71 * that's attached to a given page. If not attached
72 * to that page, will return null.
73 *
74 * @param Database $db
75 * @param int $pageid
76 * @param int $id
77 * @return Revision
78 * @access public
79 * @static
80 */
81 public static function loadFromPageId( $db, $pageid, $id = 0 ) {
82 $conds=array('page_id=rev_page','rev_page'=>intval( $pageid ), 'page_id'=>intval( $pageid ));
83 if( $id ) {
84 $conds['rev_id']=intval($id);
85 } else {
86 $conds[]='rev_id=page_latest';
87 }
88 return Revision::loadFromConds( $db, $conds );
89 }
90
91 /**
92 * Load either the current, or a specified, revision
93 * that's attached to a given page. If not attached
94 * to that page, will return null.
95 *
96 * @param Database $db
97 * @param Title $title
98 * @param int $id
99 * @return Revision
100 * @access public
101 * @static
102 */
103 public static function loadFromTitle( &$db, $title, $id = 0 ) {
104 if( $id ) {
105 $matchId = intval( $id );
106 } else {
107 $matchId = 'page_latest';
108 }
109 return Revision::loadFromConds(
110 $db,
111 array( "rev_id=$matchId",
112 'page_id=rev_page',
113 'page_namespace' => $title->getNamespace(),
114 'page_title' => $title->getDbkey() ) );
115 }
116
117 /**
118 * Load the revision for the given title with the given timestamp.
119 * WARNING: Timestamps may in some circumstances not be unique,
120 * so this isn't the best key to use.
121 *
122 * @param Database $db
123 * @param Title $title
124 * @param string $timestamp
125 * @return Revision
126 * @access public
127 * @static
128 */
129 public static function loadFromTimestamp( &$db, &$title, $timestamp ) {
130 return Revision::loadFromConds(
131 $db,
132 array( 'rev_timestamp' => $db->timestamp( $timestamp ),
133 'page_id=rev_page',
134 'page_namespace' => $title->getNamespace(),
135 'page_title' => $title->getDbkey() ) );
136 }
137
138 /**
139 * Given a set of conditions, fetch a revision.
140 *
141 * @param array $conditions
142 * @return Revision
143 * @access private
144 * @static
145 */
146 private static function newFromConds( $conditions ) {
147 $db = wfGetDB( DB_SLAVE );
148 $row = Revision::loadFromConds( $db, $conditions );
149 if( is_null( $row ) ) {
150 $dbw = wfGetDB( DB_MASTER );
151 $row = Revision::loadFromConds( $dbw, $conditions );
152 }
153 return $row;
154 }
155
156 /**
157 * Given a set of conditions, fetch a revision from
158 * the given database connection.
159 *
160 * @param Database $db
161 * @param array $conditions
162 * @return Revision
163 * @access private
164 * @static
165 */
166 private static function loadFromConds( $db, $conditions ) {
167 $res = Revision::fetchFromConds( $db, $conditions );
168 if( $res ) {
169 $row = $res->fetchObject();
170 $res->free();
171 if( $row ) {
172 $ret = new Revision( $row );
173 return $ret;
174 }
175 }
176 $ret = null;
177 return $ret;
178 }
179
180 /**
181 * Return a wrapper for a series of database rows to
182 * fetch all of a given page's revisions in turn.
183 * Each row can be fed to the constructor to get objects.
184 *
185 * @param Title $title
186 * @return ResultWrapper
187 * @access public
188 * @static
189 */
190 public static function fetchAllRevisions( &$title ) {
191 return Revision::fetchFromConds(
192 wfGetDB( DB_SLAVE ),
193 array( 'page_namespace' => $title->getNamespace(),
194 'page_title' => $title->getDbkey(),
195 'page_id=rev_page' ) );
196 }
197
198 /**
199 * Return a wrapper for a series of database rows to
200 * fetch all of a given page's revisions in turn.
201 * Each row can be fed to the constructor to get objects.
202 *
203 * @param Title $title
204 * @return ResultWrapper
205 * @access public
206 * @static
207 */
208 public static function fetchRevision( &$title ) {
209 return Revision::fetchFromConds(
210 wfGetDB( DB_SLAVE ),
211 array( 'rev_id=page_latest',
212 'page_namespace' => $title->getNamespace(),
213 'page_title' => $title->getDbkey(),
214 'page_id=rev_page' ) );
215 }
216
217 /**
218 * Given a set of conditions, return a ResultWrapper
219 * which will return matching database rows with the
220 * fields necessary to build Revision objects.
221 *
222 * @param Database $db
223 * @param array $conditions
224 * @return ResultWrapper
225 * @access private
226 * @static
227 */
228 private static function fetchFromConds( $db, $conditions ) {
229 $res = $db->select(
230 array( 'page', 'revision' ),
231 array( 'page_namespace',
232 'page_title',
233 'page_latest',
234 'rev_id',
235 'rev_page',
236 'rev_text_id',
237 'rev_comment',
238 'rev_user_text',
239 'rev_user',
240 'rev_minor_edit',
241 'rev_timestamp',
242 'rev_deleted',
243 'rev_len' ),
244 $conditions,
245 'Revision::fetchRow',
246 array( 'LIMIT' => 1 ) );
247 $ret = $db->resultObject( $res );
248 return $ret;
249 }
250
251 /**
252 * @param object $row
253 * @access private
254 */
255 function Revision( $row ) {
256 if( is_object( $row ) ) {
257 $this->mId = intval( $row->rev_id );
258 $this->mPage = intval( $row->rev_page );
259 $this->mTextId = intval( $row->rev_text_id );
260 $this->mComment = $row->rev_comment;
261 $this->mUserText = $row->rev_user_text;
262 $this->mUser = intval( $row->rev_user );
263 $this->mMinorEdit = intval( $row->rev_minor_edit );
264 $this->mTimestamp = $row->rev_timestamp;
265 $this->mDeleted = intval( $row->rev_deleted );
266
267 if (is_null($row->rev_len))
268 $this->mSize = null;
269 else
270 $this->mSize = intval( $row->rev_len );
271
272 if( isset( $row->page_latest ) ) {
273 $this->mCurrent = ( $row->rev_id == $row->page_latest );
274 $this->mTitle = Title::makeTitle( $row->page_namespace,
275 $row->page_title );
276 } else {
277 $this->mCurrent = false;
278 $this->mTitle = null;
279 }
280
281 // Lazy extraction...
282 $this->mText = null;
283 if( isset( $row->old_text ) ) {
284 $this->mTextRow = $row;
285 } else {
286 // 'text' table row entry will be lazy-loaded
287 $this->mTextRow = null;
288 }
289 } elseif( is_array( $row ) ) {
290 // Build a new revision to be saved...
291 global $wgUser;
292
293 $this->mId = isset( $row['id'] ) ? intval( $row['id'] ) : null;
294 $this->mPage = isset( $row['page'] ) ? intval( $row['page'] ) : null;
295 $this->mTextId = isset( $row['text_id'] ) ? intval( $row['text_id'] ) : null;
296 $this->mUserText = isset( $row['user_text'] ) ? strval( $row['user_text'] ) : $wgUser->getName();
297 $this->mUser = isset( $row['user'] ) ? intval( $row['user'] ) : $wgUser->getId();
298 $this->mMinorEdit = isset( $row['minor_edit'] ) ? intval( $row['minor_edit'] ) : 0;
299 $this->mTimestamp = isset( $row['timestamp'] ) ? strval( $row['timestamp'] ) : wfTimestamp( TS_MW );
300 $this->mDeleted = isset( $row['deleted'] ) ? intval( $row['deleted'] ) : 0;
301
302 // Enforce spacing trimming on supplied text
303 $this->mComment = isset( $row['comment'] ) ? trim( strval( $row['comment'] ) ) : null;
304 $this->mText = isset( $row['text'] ) ? rtrim( strval( $row['text'] ) ) : null;
305 $this->mTextRow = null;
306
307 $this->mTitle = null; # Load on demand if needed
308 $this->mCurrent = false;
309
310 $this->mSize = is_null($this->mText) ? null : strlen($this->mText);
311 } else {
312 throw new MWException( 'Revision constructor passed invalid row format.' );
313 }
314 }
315
316 /**#@+
317 * @access public
318 */
319
320 /**
321 * @return int
322 */
323 function getId() {
324 return $this->mId;
325 }
326
327 /**
328 * @return int
329 */
330 function getTextId() {
331 return $this->mTextId;
332 }
333
334 /**
335 * Returns the length of the text in this revision, or null if unknown.
336 */
337 function getSize() {
338 return $this->mSize;
339 }
340
341 /**
342 * Returns the title of the page associated with this entry.
343 * @return Title
344 */
345 function getTitle() {
346 if( isset( $this->mTitle ) ) {
347 return $this->mTitle;
348 }
349 $dbr = wfGetDB( DB_SLAVE );
350 $row = $dbr->selectRow(
351 array( 'page', 'revision' ),
352 array( 'page_namespace', 'page_title' ),
353 array( 'page_id=rev_page',
354 'rev_id' => $this->mId ),
355 'Revision::getTitle' );
356 if( $row ) {
357 $this->mTitle = Title::makeTitle( $row->page_namespace,
358 $row->page_title );
359 }
360 return $this->mTitle;
361 }
362
363 /**
364 * Set the title of the revision
365 * @param Title $title
366 */
367 function setTitle( $title ) {
368 $this->mTitle = $title;
369 }
370
371 /**
372 * @return int
373 */
374 function getPage() {
375 return $this->mPage;
376 }
377
378 /**
379 * Fetch revision's user id if it's available to all users
380 * @return int
381 */
382 function getUser() {
383 if( $this->isDeleted( self::DELETED_USER ) ) {
384 return 0;
385 } else {
386 return $this->mUser;
387 }
388 }
389
390 /**
391 * Fetch revision's user id without regard for the current user's permissions
392 * @return string
393 */
394 function getRawUser() {
395 return $this->mUser;
396 }
397
398 /**
399 * Fetch revision's username if it's available to all users
400 * @return string
401 */
402 function getUserText() {
403 if( $this->isDeleted( self::DELETED_USER ) ) {
404 return "";
405 } else {
406 return $this->mUserText;
407 }
408 }
409
410 /**
411 * Fetch revision's username without regard for view restrictions
412 * @return string
413 */
414 function getRawUserText() {
415 return $this->mUserText;
416 }
417
418 /**
419 * Fetch revision comment if it's available to all users
420 * @return string
421 */
422 function getComment() {
423 if( $this->isDeleted( self::DELETED_COMMENT ) ) {
424 return "";
425 } else {
426 return $this->mComment;
427 }
428 }
429
430 /**
431 * Fetch revision comment without regard for the current user's permissions
432 * @return string
433 */
434 function getRawComment() {
435 return $this->mComment;
436 }
437
438 /**
439 * @return bool
440 */
441 function isMinor() {
442 return (bool)$this->mMinorEdit;
443 }
444
445 /**
446 * int $field one of DELETED_* bitfield constants
447 * @return bool
448 */
449 function isDeleted( $field ) {
450 return ($this->mDeleted & $field) == $field;
451 }
452
453 /**
454 * Fetch revision text if it's available to all users
455 * @return string
456 */
457 function getText() {
458 if( $this->isDeleted( self::DELETED_TEXT ) ) {
459 return "";
460 } else {
461 return $this->getRawText();
462 }
463 }
464
465 /**
466 * Fetch revision text without regard for view restrictions
467 * @return string
468 */
469 function getRawText() {
470 if( is_null( $this->mText ) ) {
471 // Revision text is immutable. Load on demand:
472 $this->mText = $this->loadText();
473 }
474 return $this->mText;
475 }
476
477 /**
478 * Fetch revision text if it's available to THIS user
479 * @return string
480 */
481 function revText() {
482 if( !$this->userCan( self::DELETED_TEXT ) ) {
483 return "";
484 } else {
485 return $this->getRawText();
486 }
487 }
488
489 /**
490 * @return string
491 */
492 function getTimestamp() {
493 return wfTimestamp(TS_MW, $this->mTimestamp);
494 }
495
496 /**
497 * @return bool
498 */
499 function isCurrent() {
500 return $this->mCurrent;
501 }
502
503 /**
504 * @return Revision
505 */
506 function getPrevious() {
507 $prev = $this->mTitle->getPreviousRevisionID( $this->mId );
508 if ( $prev ) {
509 return Revision::newFromTitle( $this->mTitle, $prev );
510 } else {
511 return null;
512 }
513 }
514
515 /**
516 * @return Revision
517 */
518 function getNext() {
519 $next = $this->mTitle->getNextRevisionID( $this->mId );
520 if ( $next ) {
521 return Revision::newFromTitle( $this->mTitle, $next );
522 } else {
523 return null;
524 }
525 }
526 /**#@-*/
527
528 /**
529 * Get revision text associated with an old or archive row
530 * $row is usually an object from wfFetchRow(), both the flags and the text
531 * field must be included
532 * @static
533 * @param integer $row Id of a row
534 * @param string $prefix table prefix (default 'old_')
535 * @return string $text|false the text requested
536 */
537 public static function getRevisionText( $row, $prefix = 'old_' ) {
538 $fname = 'Revision::getRevisionText';
539 wfProfileIn( $fname );
540
541 # Get data
542 $textField = $prefix . 'text';
543 $flagsField = $prefix . 'flags';
544
545 if( isset( $row->$flagsField ) ) {
546 $flags = explode( ',', $row->$flagsField );
547 } else {
548 $flags = array();
549 }
550
551 if( isset( $row->$textField ) ) {
552 $text = $row->$textField;
553 } else {
554 wfProfileOut( $fname );
555 return false;
556 }
557
558 # Use external methods for external objects, text in table is URL-only then
559 if ( in_array( 'external', $flags ) ) {
560 $url=$text;
561 @list(/* $proto */,$path)=explode('://',$url,2);
562 if ($path=="") {
563 wfProfileOut( $fname );
564 return false;
565 }
566 $text=ExternalStore::fetchFromURL($url);
567 }
568
569 // If the text was fetched without an error, convert it
570 if ( $text !== false ) {
571 if( in_array( 'gzip', $flags ) ) {
572 # Deal with optional compression of archived pages.
573 # This can be done periodically via maintenance/compressOld.php, and
574 # as pages are saved if $wgCompressRevisions is set.
575 $text = gzinflate( $text );
576 }
577
578 if( in_array( 'object', $flags ) ) {
579 # Generic compressed storage
580 $obj = unserialize( $text );
581 if ( !is_object( $obj ) ) {
582 // Invalid object
583 wfProfileOut( $fname );
584 return false;
585 }
586 $text = $obj->getText();
587 }
588
589 global $wgLegacyEncoding;
590 if( $wgLegacyEncoding && !in_array( 'utf-8', $flags ) ) {
591 # Old revisions kept around in a legacy encoding?
592 # Upconvert on demand.
593 global $wgInputEncoding, $wgContLang;
594 $text = $wgContLang->iconv( $wgLegacyEncoding, $wgInputEncoding . '//IGNORE', $text );
595 }
596 }
597 wfProfileOut( $fname );
598 return $text;
599 }
600
601 /**
602 * If $wgCompressRevisions is enabled, we will compress data.
603 * The input string is modified in place.
604 * Return value is the flags field: contains 'gzip' if the
605 * data is compressed, and 'utf-8' if we're saving in UTF-8
606 * mode.
607 *
608 * @static
609 * @param mixed $text reference to a text
610 * @return string
611 */
612 function compressRevisionText( &$text ) {
613 global $wgCompressRevisions;
614 $flags = array();
615
616 # Revisions not marked this way will be converted
617 # on load if $wgLegacyCharset is set in the future.
618 $flags[] = 'utf-8';
619
620 if( $wgCompressRevisions ) {
621 if( function_exists( 'gzdeflate' ) ) {
622 $text = gzdeflate( $text );
623 $flags[] = 'gzip';
624 } else {
625 wfDebug( "Revision::compressRevisionText() -- no zlib support, not compressing\n" );
626 }
627 }
628 return implode( ',', $flags );
629 }
630
631 /**
632 * Insert a new revision into the database, returning the new revision ID
633 * number on success and dies horribly on failure.
634 *
635 * @param Database $dbw
636 * @return int
637 */
638 function insertOn( &$dbw ) {
639 global $wgDefaultExternalStore;
640
641 $fname = 'Revision::insertOn';
642 wfProfileIn( $fname );
643
644 $data = $this->mText;
645 $flags = Revision::compressRevisionText( $data );
646
647 # Write to external storage if required
648 if ( $wgDefaultExternalStore ) {
649 if ( is_array( $wgDefaultExternalStore ) ) {
650 // Distribute storage across multiple clusters
651 $store = $wgDefaultExternalStore[mt_rand(0, count( $wgDefaultExternalStore ) - 1)];
652 } else {
653 $store = $wgDefaultExternalStore;
654 }
655 // Store and get the URL
656 $data = ExternalStore::insert( $store, $data );
657 if ( !$data ) {
658 # This should only happen in the case of a configuration error, where the external store is not valid
659 throw new MWException( "Unable to store text to external storage $store" );
660 }
661 if ( $flags ) {
662 $flags .= ',';
663 }
664 $flags .= 'external';
665 }
666
667 # Record the text (or external storage URL) to the text table
668 if( !isset( $this->mTextId ) ) {
669 $old_id = $dbw->nextSequenceValue( 'text_old_id_val' );
670 $dbw->insert( 'text',
671 array(
672 'old_id' => $old_id,
673 'old_text' => $data,
674 'old_flags' => $flags,
675 ), $fname
676 );
677 $this->mTextId = $dbw->insertId();
678 }
679
680 # Record the edit in revisions
681 $rev_id = isset( $this->mId )
682 ? $this->mId
683 : $dbw->nextSequenceValue( 'rev_rev_id_val' );
684 $dbw->insert( 'revision',
685 array(
686 'rev_id' => $rev_id,
687 'rev_page' => $this->mPage,
688 'rev_text_id' => $this->mTextId,
689 'rev_comment' => $this->mComment,
690 'rev_minor_edit' => $this->mMinorEdit ? 1 : 0,
691 'rev_user' => $this->mUser,
692 'rev_user_text' => $this->mUserText,
693 'rev_timestamp' => $dbw->timestamp( $this->mTimestamp ),
694 'rev_deleted' => $this->mDeleted,
695 'rev_len' => strlen($this->mText),
696 ), $fname
697 );
698
699 $this->mId = !is_null($rev_id) ? $rev_id : $dbw->insertId();
700 wfProfileOut( $fname );
701 return $this->mId;
702 }
703
704 /**
705 * Lazy-load the revision's text.
706 * Currently hardcoded to the 'text' table storage engine.
707 *
708 * @return string
709 * @access private
710 */
711 function loadText() {
712 $fname = 'Revision::loadText';
713 wfProfileIn( $fname );
714
715 // Caching may be beneficial for massive use of external storage
716 global $wgRevisionCacheExpiry, $wgMemc;
717 $key = wfMemcKey( 'revisiontext', 'textid', $this->getTextId() );
718 if( $wgRevisionCacheExpiry ) {
719 $text = $wgMemc->get( $key );
720 if( is_string( $text ) ) {
721 wfProfileOut( $fname );
722 return $text;
723 }
724 }
725
726 // If we kept data for lazy extraction, use it now...
727 if ( isset( $this->mTextRow ) ) {
728 $row = $this->mTextRow;
729 $this->mTextRow = null;
730 } else {
731 $row = null;
732 }
733
734 if( !$row ) {
735 // Text data is immutable; check slaves first.
736 $dbr = wfGetDB( DB_SLAVE );
737 $row = $dbr->selectRow( 'text',
738 array( 'old_text', 'old_flags' ),
739 array( 'old_id' => $this->getTextId() ),
740 $fname);
741 }
742
743 if( !$row ) {
744 // Possible slave lag!
745 $dbw = wfGetDB( DB_MASTER );
746 $row = $dbw->selectRow( 'text',
747 array( 'old_text', 'old_flags' ),
748 array( 'old_id' => $this->getTextId() ),
749 $fname);
750 }
751
752 $text = Revision::getRevisionText( $row );
753
754 if( $wgRevisionCacheExpiry ) {
755 $wgMemc->set( $key, $text, $wgRevisionCacheExpiry );
756 }
757
758 wfProfileOut( $fname );
759
760 return $text;
761 }
762
763 /**
764 * Create a new null-revision for insertion into a page's
765 * history. This will not re-save the text, but simply refer
766 * to the text from the previous version.
767 *
768 * Such revisions can for instance identify page rename
769 * operations and other such meta-modifications.
770 *
771 * @param Database $dbw
772 * @param int $pageId ID number of the page to read from
773 * @param string $summary
774 * @param bool $minor
775 * @return Revision
776 */
777 function newNullRevision( &$dbw, $pageId, $summary, $minor ) {
778 $fname = 'Revision::newNullRevision';
779 wfProfileIn( $fname );
780
781 $current = $dbw->selectRow(
782 array( 'page', 'revision' ),
783 array( 'page_latest', 'rev_text_id' ),
784 array(
785 'page_id' => $pageId,
786 'page_latest=rev_id',
787 ),
788 $fname );
789
790 if( $current ) {
791 $revision = new Revision( array(
792 'page' => $pageId,
793 'comment' => $summary,
794 'minor_edit' => $minor,
795 'text_id' => $current->rev_text_id,
796 ) );
797 } else {
798 $revision = null;
799 }
800
801 wfProfileOut( $fname );
802 return $revision;
803 }
804
805 /**
806 * Determine if the current user is allowed to view a particular
807 * field of this revision, if it's marked as deleted.
808 * @param int $field one of self::DELETED_TEXT,
809 * self::DELETED_COMMENT,
810 * self::DELETED_USER
811 * @return bool
812 */
813 function userCan( $field ) {
814 if( ( $this->mDeleted & $field ) == $field ) {
815 global $wgUser;
816 $permission = ( $this->mDeleted & self::DELETED_RESTRICTED ) == self::DELETED_RESTRICTED
817 ? 'hiderevision'
818 : 'deleterevision';
819 wfDebug( "Checking for $permission due to $field match on $this->mDeleted\n" );
820 return $wgUser->isAllowed( $permission );
821 } else {
822 return true;
823 }
824 }
825
826
827 /**
828 * Get rev_timestamp from rev_id, without loading the rest of the row
829 * @param integer $id
830 */
831 static function getTimestampFromID( $id ) {
832 $dbr = wfGetDB( DB_SLAVE );
833 $timestamp = $dbr->selectField( 'revision', 'rev_timestamp',
834 array( 'rev_id' => $id ), __METHOD__ );
835 if ( $timestamp === false ) {
836 # Not in slave, try master
837 $dbw = wfGetDB( DB_MASTER );
838 $timestamp = $dbw->selectField( 'revision', 'rev_timestamp',
839 array( 'rev_id' => $id ), __METHOD__ );
840 }
841 return $timestamp;
842 }
843
844 static function countByPageId( $db, $id ) {
845 $row = $db->selectRow( 'revision', 'COUNT(*) AS revCount',
846 array( 'rev_page' => $id ), __METHOD__ );
847 if( $row ) {
848 return $row->revCount;
849 }
850 return 0;
851 }
852
853 static function countByTitle( $db, $title ) {
854 $id = $title->getArticleId();
855 if( $id ) {
856 return Revision::countByPageId( $db, $id );
857 }
858 return 0;
859 }
860 }
861
862 /**
863 * Aliases for backwards compatibility with 1.6
864 */
865 define( 'MW_REV_DELETED_TEXT', Revision::DELETED_TEXT );
866 define( 'MW_REV_DELETED_COMMENT', Revision::DELETED_COMMENT );
867 define( 'MW_REV_DELETED_USER', Revision::DELETED_USER );
868 define( 'MW_REV_DELETED_RESTRICTED', Revision::DELETED_RESTRICTED );
869
870
871 ?>