Index: trunk/phase3/includes/WikiPage.php |
— | — | @@ -487,6 +487,39 @@ |
488 | 488 | } |
489 | 489 | |
490 | 490 | /** |
| 491 | + * Loads page_touched and returns a value indicating if it should be used |
| 492 | + * @return boolean true if not a redirect |
| 493 | + */ |
| 494 | + public function checkTouched() { |
| 495 | + if ( !$this->mDataLoaded ) { |
| 496 | + $this->loadPageData(); |
| 497 | + } |
| 498 | + return !$this->mIsRedirect; |
| 499 | + } |
| 500 | + |
| 501 | + /** |
| 502 | + * Get the page_touched field |
| 503 | + * @return string containing GMT timestamp |
| 504 | + */ |
| 505 | + public function getTouched() { |
| 506 | + if ( !$this->mDataLoaded ) { |
| 507 | + $this->loadPageData(); |
| 508 | + } |
| 509 | + return $this->mTouched; |
| 510 | + } |
| 511 | + |
| 512 | + /** |
| 513 | + * Get the page_latest field |
| 514 | + * @return integer rev_id of current revision |
| 515 | + */ |
| 516 | + public function getLatest() { |
| 517 | + if ( !$this->mDataLoaded ) { |
| 518 | + $this->loadPageData(); |
| 519 | + } |
| 520 | + return (int)$this->mLatest; |
| 521 | + } |
| 522 | + |
| 523 | + /** |
491 | 524 | * Loads everything except the text |
492 | 525 | * This isn't necessary for all uses, so it's only done if needed. |
493 | 526 | */ |
— | — | @@ -639,6 +672,29 @@ |
640 | 673 | } |
641 | 674 | |
642 | 675 | /** |
| 676 | + * Get the cached timestamp for the last time the page changed. |
| 677 | + * This is only used to help handle slave lag by comparing to page_touched. |
| 678 | + * @return string MW timestamp |
| 679 | + */ |
| 680 | + protected function getCachedLastEditTime() { |
| 681 | + global $wgMemc; |
| 682 | + $key = wfMemcKey( 'page-lastedit', md5( $this->mTitle->getPrefixedDBkey() ) ); |
| 683 | + return $wgMemc->get( $key ); |
| 684 | + } |
| 685 | + |
| 686 | + /** |
| 687 | + * Set the cached timestamp for the last time the page changed. |
| 688 | + * This is only used to help handle slave lag by comparing to page_touched. |
| 689 | + * @param $timestamp string |
| 690 | + * @return void |
| 691 | + */ |
| 692 | + public function setCachedLastEditTime( $timestamp ) { |
| 693 | + global $wgMemc; |
| 694 | + $key = wfMemcKey( 'page-lastedit', md5( $this->mTitle->getPrefixedDBkey() ) ); |
| 695 | + $wgMemc->set( $key, wfTimestamp( TS_MW, $timestamp ), 60*15 ); |
| 696 | + } |
| 697 | + |
| 698 | + /** |
643 | 699 | * Get a list of users who have edited this article, not including the user who made |
644 | 700 | * the most recent revision, which you can get from $article->getUser() if you want it |
645 | 701 | * @return UserArrayFromResult |
— | — | @@ -690,6 +746,58 @@ |
691 | 747 | } |
692 | 748 | |
693 | 749 | /** |
| 750 | + * Get the last N authors |
| 751 | + * @param $num Integer: number of revisions to get |
| 752 | + * @param $revLatest String: the latest rev_id, selected from the master (optional) |
| 753 | + * @return array Array of authors, duplicates not removed |
| 754 | + */ |
| 755 | + public function getLastNAuthors( $num, $revLatest = 0 ) { |
| 756 | + wfProfileIn( __METHOD__ ); |
| 757 | + // First try the slave |
| 758 | + // If that doesn't have the latest revision, try the master |
| 759 | + $continue = 2; |
| 760 | + $db = wfGetDB( DB_SLAVE ); |
| 761 | + |
| 762 | + do { |
| 763 | + $res = $db->select( array( 'page', 'revision' ), |
| 764 | + array( 'rev_id', 'rev_user_text' ), |
| 765 | + array( |
| 766 | + 'page_namespace' => $this->mTitle->getNamespace(), |
| 767 | + 'page_title' => $this->mTitle->getDBkey(), |
| 768 | + 'rev_page = page_id' |
| 769 | + ), __METHOD__, |
| 770 | + array( |
| 771 | + 'ORDER BY' => 'rev_timestamp DESC', |
| 772 | + 'LIMIT' => $num |
| 773 | + ) |
| 774 | + ); |
| 775 | + |
| 776 | + if ( !$res ) { |
| 777 | + wfProfileOut( __METHOD__ ); |
| 778 | + return array(); |
| 779 | + } |
| 780 | + |
| 781 | + $row = $db->fetchObject( $res ); |
| 782 | + |
| 783 | + if ( $continue == 2 && $revLatest && $row->rev_id != $revLatest ) { |
| 784 | + $db = wfGetDB( DB_MASTER ); |
| 785 | + $continue--; |
| 786 | + } else { |
| 787 | + $continue = 0; |
| 788 | + } |
| 789 | + } while ( $continue ); |
| 790 | + |
| 791 | + $authors = array( $row->rev_user_text ); |
| 792 | + |
| 793 | + foreach ( $res as $row ) { |
| 794 | + $authors[] = $row->rev_user_text; |
| 795 | + } |
| 796 | + |
| 797 | + wfProfileOut( __METHOD__ ); |
| 798 | + return $authors; |
| 799 | + } |
| 800 | + |
| 801 | + /** |
694 | 802 | * Should the parser cache be used? |
695 | 803 | * |
696 | 804 | * @param $parserOptions ParserOptions to check |
— | — | @@ -746,6 +854,26 @@ |
747 | 855 | } |
748 | 856 | |
749 | 857 | /** |
| 858 | + * Do standard deferred updates after page view |
| 859 | + * @param $user User The relevant user |
| 860 | + */ |
| 861 | + public function doViewUpdates( User $user ) { |
| 862 | + global $wgDisableCounters; |
| 863 | + if ( wfReadOnly() ) { |
| 864 | + return; |
| 865 | + } |
| 866 | + |
| 867 | + # Don't update page view counters on views from bot users (bug 14044) |
| 868 | + if ( !$wgDisableCounters && !$user->isAllowed( 'bot' ) && $this->mTitle->exists() ) { |
| 869 | + DeferredUpdates::addUpdate( new ViewCountUpdate( $this->getId() ) ); |
| 870 | + DeferredUpdates::addUpdate( new SiteStatsUpdate( 1, 0, 0 ) ); |
| 871 | + } |
| 872 | + |
| 873 | + # Update newtalk / watchlist notification status |
| 874 | + $user->clearNotification( $this->mTitle ); |
| 875 | + } |
| 876 | + |
| 877 | + /** |
750 | 878 | * Perform the actions of a page purging |
751 | 879 | */ |
752 | 880 | public function doPurge() { |
— | — | @@ -877,29 +1005,6 @@ |
878 | 1006 | } |
879 | 1007 | |
880 | 1008 | /** |
881 | | - * Get the cached timestamp for the last time the page changed. |
882 | | - * This is only used to help handle slave lag by comparing to page_touched. |
883 | | - * @return string MW timestamp |
884 | | - */ |
885 | | - protected function getCachedLastEditTime() { |
886 | | - global $wgMemc; |
887 | | - $key = wfMemcKey( 'page-lastedit', md5( $this->mTitle->getPrefixedDBkey() ) ); |
888 | | - return $wgMemc->get( $key ); |
889 | | - } |
890 | | - |
891 | | - /** |
892 | | - * Set the cached timestamp for the last time the page changed. |
893 | | - * This is only used to help handle slave lag by comparing to page_touched. |
894 | | - * @param $timestamp string |
895 | | - * @return void |
896 | | - */ |
897 | | - public function setCachedLastEditTime( $timestamp ) { |
898 | | - global $wgMemc; |
899 | | - $key = wfMemcKey( 'page-lastedit', md5( $this->mTitle->getPrefixedDBkey() ) ); |
900 | | - $wgMemc->set( $key, wfTimestamp( TS_MW, $timestamp ), 60*15 ); |
901 | | - } |
902 | | - |
903 | | - /** |
904 | 1009 | * Add row to the redirect table if this is a redirect, remove otherwise. |
905 | 1010 | * |
906 | 1011 | * @param $dbw DatabaseBase |
— | — | @@ -1328,6 +1433,208 @@ |
1329 | 1434 | } |
1330 | 1435 | |
1331 | 1436 | /** |
| 1437 | + * Get parser options suitable for rendering the primary article wikitext |
| 1438 | + * @param User|string $user User object or 'canonical' |
| 1439 | + * @return ParserOptions |
| 1440 | + */ |
| 1441 | + public function makeParserOptions( $user ) { |
| 1442 | + global $wgContLang; |
| 1443 | + if ( $user instanceof User ) { // settings per user (even anons) |
| 1444 | + $options = ParserOptions::newFromUser( $user ); |
| 1445 | + } else { // canonical settings |
| 1446 | + $options = ParserOptions::newFromUserAndLang( new User, $wgContLang ); |
| 1447 | + } |
| 1448 | + $options->enableLimitReport(); // show inclusion/loop reports |
| 1449 | + $options->setTidy( true ); // fix bad HTML |
| 1450 | + return $options; |
| 1451 | + } |
| 1452 | + |
| 1453 | + /** |
| 1454 | + * Prepare text which is about to be saved. |
| 1455 | + * Returns a stdclass with source, pst and output members |
| 1456 | + */ |
| 1457 | + public function prepareTextForEdit( $text, $revid = null, User $user = null ) { |
| 1458 | + global $wgParser, $wgContLang, $wgUser; |
| 1459 | + $user = is_null( $user ) ? $wgUser : $user; |
| 1460 | + // @TODO fixme: check $user->getId() here??? |
| 1461 | + if ( $this->mPreparedEdit |
| 1462 | + && $this->mPreparedEdit->newText == $text |
| 1463 | + && $this->mPreparedEdit->revid == $revid |
| 1464 | + ) { |
| 1465 | + // Already prepared |
| 1466 | + return $this->mPreparedEdit; |
| 1467 | + } |
| 1468 | + |
| 1469 | + $popts = ParserOptions::newFromUserAndLang( $user, $wgContLang ); |
| 1470 | + wfRunHooks( 'ArticlePrepareTextForEdit', array( $this, $popts ) ); |
| 1471 | + |
| 1472 | + $edit = (object)array(); |
| 1473 | + $edit->revid = $revid; |
| 1474 | + $edit->newText = $text; |
| 1475 | + $edit->pst = $wgParser->preSaveTransform( $text, $this->mTitle, $user, $popts ); |
| 1476 | + $edit->popts = $this->makeParserOptions( 'canonical' ); |
| 1477 | + $edit->output = $wgParser->parse( $edit->pst, $this->mTitle, $edit->popts, true, true, $revid ); |
| 1478 | + $edit->oldText = $this->getRawText(); |
| 1479 | + |
| 1480 | + $this->mPreparedEdit = $edit; |
| 1481 | + |
| 1482 | + return $edit; |
| 1483 | + } |
| 1484 | + |
| 1485 | + /** |
| 1486 | + * Do standard deferred updates after page edit. |
| 1487 | + * Update links tables, site stats, search index and message cache. |
| 1488 | + * Purges pages that include this page if the text was changed here. |
| 1489 | + * Every 100th edit, prune the recent changes table. |
| 1490 | + * |
| 1491 | + * @private |
| 1492 | + * @param $revision Revision object |
| 1493 | + * @param $user User object that did the revision |
| 1494 | + * @param $options Array of options, following indexes are used: |
| 1495 | + * - changed: boolean, whether the revision changed the content (default true) |
| 1496 | + * - created: boolean, whether the revision created the page (default false) |
| 1497 | + * - oldcountable: boolean or null (default null): |
| 1498 | + * - boolean: whether the page was counted as an article before that |
| 1499 | + * revision, only used in changed is true and created is false |
| 1500 | + * - null: don't change the article count |
| 1501 | + */ |
| 1502 | + public function doEditUpdates( Revision $revision, User $user, array $options = array() ) { |
| 1503 | + global $wgEnableParserCache; |
| 1504 | + |
| 1505 | + wfProfileIn( __METHOD__ ); |
| 1506 | + |
| 1507 | + $options += array( 'changed' => true, 'created' => false, 'oldcountable' => null ); |
| 1508 | + $text = $revision->getText(); |
| 1509 | + |
| 1510 | + # Parse the text |
| 1511 | + # Be careful not to double-PST: $text is usually already PST-ed once |
| 1512 | + if ( !$this->mPreparedEdit || $this->mPreparedEdit->output->getFlag( 'vary-revision' ) ) { |
| 1513 | + wfDebug( __METHOD__ . ": No prepared edit or vary-revision is set...\n" ); |
| 1514 | + $editInfo = $this->prepareTextForEdit( $text, $revision->getId(), $user ); |
| 1515 | + } else { |
| 1516 | + wfDebug( __METHOD__ . ": No vary-revision, using prepared edit...\n" ); |
| 1517 | + $editInfo = $this->mPreparedEdit; |
| 1518 | + } |
| 1519 | + |
| 1520 | + # Save it to the parser cache |
| 1521 | + if ( $wgEnableParserCache ) { |
| 1522 | + $parserCache = ParserCache::singleton(); |
| 1523 | + $parserCache->save( $editInfo->output, $this, $editInfo->popts ); |
| 1524 | + } |
| 1525 | + |
| 1526 | + # Update the links tables |
| 1527 | + $u = new LinksUpdate( $this->mTitle, $editInfo->output ); |
| 1528 | + $u->doUpdate(); |
| 1529 | + |
| 1530 | + wfRunHooks( 'ArticleEditUpdates', array( &$this, &$editInfo, $options['changed'] ) ); |
| 1531 | + |
| 1532 | + if ( wfRunHooks( 'ArticleEditUpdatesDeleteFromRecentchanges', array( &$this ) ) ) { |
| 1533 | + if ( 0 == mt_rand( 0, 99 ) ) { |
| 1534 | + // Flush old entries from the `recentchanges` table; we do this on |
| 1535 | + // random requests so as to avoid an increase in writes for no good reason |
| 1536 | + global $wgRCMaxAge; |
| 1537 | + |
| 1538 | + $dbw = wfGetDB( DB_MASTER ); |
| 1539 | + $cutoff = $dbw->timestamp( time() - $wgRCMaxAge ); |
| 1540 | + $dbw->delete( |
| 1541 | + 'recentchanges', |
| 1542 | + array( "rc_timestamp < '$cutoff'" ), |
| 1543 | + __METHOD__ |
| 1544 | + ); |
| 1545 | + } |
| 1546 | + } |
| 1547 | + |
| 1548 | + if ( !$this->mTitle->exists() ) { |
| 1549 | + wfProfileOut( __METHOD__ ); |
| 1550 | + return; |
| 1551 | + } |
| 1552 | + |
| 1553 | + $id = $this->getId(); |
| 1554 | + $title = $this->mTitle->getPrefixedDBkey(); |
| 1555 | + $shortTitle = $this->mTitle->getDBkey(); |
| 1556 | + |
| 1557 | + if ( !$options['changed'] ) { |
| 1558 | + $good = 0; |
| 1559 | + $total = 0; |
| 1560 | + } elseif ( $options['created'] ) { |
| 1561 | + $good = (int)$this->isCountable( $editInfo ); |
| 1562 | + $total = 1; |
| 1563 | + } elseif ( $options['oldcountable'] !== null ) { |
| 1564 | + $good = (int)$this->isCountable( $editInfo ) - (int)$options['oldcountable']; |
| 1565 | + $total = 0; |
| 1566 | + } else { |
| 1567 | + $good = 0; |
| 1568 | + $total = 0; |
| 1569 | + } |
| 1570 | + |
| 1571 | + DeferredUpdates::addUpdate( new SiteStatsUpdate( 0, 1, $good, $total ) ); |
| 1572 | + DeferredUpdates::addUpdate( new SearchUpdate( $id, $title, $text ) ); |
| 1573 | + |
| 1574 | + # If this is another user's talk page, update newtalk. |
| 1575 | + # Don't do this if $options['changed'] = false (null-edits) nor if |
| 1576 | + # it's a minor edit and the user doesn't want notifications for those. |
| 1577 | + if ( $options['changed'] |
| 1578 | + && $this->mTitle->getNamespace() == NS_USER_TALK |
| 1579 | + && $shortTitle != $user->getTitleKey() |
| 1580 | + && !( $revision->isMinor() && $user->isAllowed( 'nominornewtalk' ) ) |
| 1581 | + ) { |
| 1582 | + if ( wfRunHooks( 'ArticleEditUpdateNewTalk', array( &$this ) ) ) { |
| 1583 | + $other = User::newFromName( $shortTitle, false ); |
| 1584 | + if ( !$other ) { |
| 1585 | + wfDebug( __METHOD__ . ": invalid username\n" ); |
| 1586 | + } elseif ( User::isIP( $shortTitle ) ) { |
| 1587 | + // An anonymous user |
| 1588 | + $other->setNewtalk( true ); |
| 1589 | + } elseif ( $other->isLoggedIn() ) { |
| 1590 | + $other->setNewtalk( true ); |
| 1591 | + } else { |
| 1592 | + wfDebug( __METHOD__ . ": don't need to notify a nonexistent user\n" ); |
| 1593 | + } |
| 1594 | + } |
| 1595 | + } |
| 1596 | + |
| 1597 | + if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) { |
| 1598 | + MessageCache::singleton()->replace( $shortTitle, $text ); |
| 1599 | + } |
| 1600 | + |
| 1601 | + if( $options['created'] ) { |
| 1602 | + self::onArticleCreate( $this->mTitle ); |
| 1603 | + } else { |
| 1604 | + self::onArticleEdit( $this->mTitle ); |
| 1605 | + } |
| 1606 | + |
| 1607 | + wfProfileOut( __METHOD__ ); |
| 1608 | + } |
| 1609 | + |
| 1610 | + /** |
| 1611 | + * Edit an article without doing all that other stuff |
| 1612 | + * The article must already exist; link tables etc |
| 1613 | + * are not updated, caches are not flushed. |
| 1614 | + * |
| 1615 | + * @param $text String: text submitted |
| 1616 | + * @param $user User The relevant user |
| 1617 | + * @param $comment String: comment submitted |
| 1618 | + * @param $minor Boolean: whereas it's a minor modification |
| 1619 | + */ |
| 1620 | + public function doQuickEdit( $text, User $user, $comment = '', $minor = 0 ) { |
| 1621 | + wfProfileIn( __METHOD__ ); |
| 1622 | + |
| 1623 | + $dbw = wfGetDB( DB_MASTER ); |
| 1624 | + $revision = new Revision( array( |
| 1625 | + 'page' => $this->getId(), |
| 1626 | + 'text' => $text, |
| 1627 | + 'comment' => $comment, |
| 1628 | + 'minor_edit' => $minor ? 1 : 0, |
| 1629 | + ) ); |
| 1630 | + $revision->insertOn( $dbw ); |
| 1631 | + $this->updateRevisionOn( $dbw, $revision ); |
| 1632 | + |
| 1633 | + wfRunHooks( 'NewRevisionFromEditComplete', array( $this, $revision, false, $user ) ); |
| 1634 | + |
| 1635 | + wfProfileOut( __METHOD__ ); |
| 1636 | + } |
| 1637 | + |
| 1638 | + /** |
1332 | 1639 | * Update the article's restriction field, and leave a log entry. |
1333 | 1640 | * This works for protection both existing and non-existing pages. |
1334 | 1641 | * |
— | — | @@ -1560,80 +1867,6 @@ |
1561 | 1868 | } |
1562 | 1869 | |
1563 | 1870 | /** |
1564 | | - * Check whether the number of revisions of this page surpasses $wgDeleteRevisionsLimit |
1565 | | - * |
1566 | | - * @deprecated in 1.19; use Title::isBigDeletion() instead. |
1567 | | - * @return bool |
1568 | | - */ |
1569 | | - public function isBigDeletion() { |
1570 | | - wfDeprecated( __METHOD__, '1.19' ); |
1571 | | - return $this->mTitle->isBigDeletion(); |
1572 | | - } |
1573 | | - |
1574 | | - /** |
1575 | | - * Get the approximate revision count of this page. |
1576 | | - * |
1577 | | - * @deprecated in 1.19; use Title::estimateRevisionCount() instead. |
1578 | | - * @return int |
1579 | | - */ |
1580 | | - public function estimateRevisionCount() { |
1581 | | - wfDeprecated( __METHOD__, '1.19' ); |
1582 | | - return $this->mTitle->estimateRevisionCount(); |
1583 | | - } |
1584 | | - |
1585 | | - /** |
1586 | | - * Get the last N authors |
1587 | | - * @param $num Integer: number of revisions to get |
1588 | | - * @param $revLatest String: the latest rev_id, selected from the master (optional) |
1589 | | - * @return array Array of authors, duplicates not removed |
1590 | | - */ |
1591 | | - public function getLastNAuthors( $num, $revLatest = 0 ) { |
1592 | | - wfProfileIn( __METHOD__ ); |
1593 | | - // First try the slave |
1594 | | - // If that doesn't have the latest revision, try the master |
1595 | | - $continue = 2; |
1596 | | - $db = wfGetDB( DB_SLAVE ); |
1597 | | - |
1598 | | - do { |
1599 | | - $res = $db->select( array( 'page', 'revision' ), |
1600 | | - array( 'rev_id', 'rev_user_text' ), |
1601 | | - array( |
1602 | | - 'page_namespace' => $this->mTitle->getNamespace(), |
1603 | | - 'page_title' => $this->mTitle->getDBkey(), |
1604 | | - 'rev_page = page_id' |
1605 | | - ), __METHOD__, |
1606 | | - array( |
1607 | | - 'ORDER BY' => 'rev_timestamp DESC', |
1608 | | - 'LIMIT' => $num |
1609 | | - ) |
1610 | | - ); |
1611 | | - |
1612 | | - if ( !$res ) { |
1613 | | - wfProfileOut( __METHOD__ ); |
1614 | | - return array(); |
1615 | | - } |
1616 | | - |
1617 | | - $row = $db->fetchObject( $res ); |
1618 | | - |
1619 | | - if ( $continue == 2 && $revLatest && $row->rev_id != $revLatest ) { |
1620 | | - $db = wfGetDB( DB_MASTER ); |
1621 | | - $continue--; |
1622 | | - } else { |
1623 | | - $continue = 0; |
1624 | | - } |
1625 | | - } while ( $continue ); |
1626 | | - |
1627 | | - $authors = array( $row->rev_user_text ); |
1628 | | - |
1629 | | - foreach ( $res as $row ) { |
1630 | | - $authors[] = $row->rev_user_text; |
1631 | | - } |
1632 | | - |
1633 | | - wfProfileOut( __METHOD__ ); |
1634 | | - return $authors; |
1635 | | - } |
1636 | | - |
1637 | | - /** |
1638 | 1871 | * Back-end article deletion |
1639 | 1872 | * Deletes the article with database consistency, writes logs, purges caches |
1640 | 1873 | * |
— | — | @@ -1978,286 +2211,6 @@ |
1979 | 2212 | } |
1980 | 2213 | |
1981 | 2214 | /** |
1982 | | - * Do standard deferred updates after page view |
1983 | | - * @param $user User The relevant user |
1984 | | - */ |
1985 | | - public function doViewUpdates( User $user ) { |
1986 | | - global $wgDisableCounters; |
1987 | | - if ( wfReadOnly() ) { |
1988 | | - return; |
1989 | | - } |
1990 | | - |
1991 | | - # Don't update page view counters on views from bot users (bug 14044) |
1992 | | - if ( !$wgDisableCounters && !$user->isAllowed( 'bot' ) && $this->mTitle->exists() ) { |
1993 | | - DeferredUpdates::addUpdate( new ViewCountUpdate( $this->getId() ) ); |
1994 | | - DeferredUpdates::addUpdate( new SiteStatsUpdate( 1, 0, 0 ) ); |
1995 | | - } |
1996 | | - |
1997 | | - # Update newtalk / watchlist notification status |
1998 | | - $user->clearNotification( $this->mTitle ); |
1999 | | - } |
2000 | | - |
2001 | | - /** |
2002 | | - * Prepare text which is about to be saved. |
2003 | | - * Returns a stdclass with source, pst and output members |
2004 | | - */ |
2005 | | - public function prepareTextForEdit( $text, $revid = null, User $user = null ) { |
2006 | | - global $wgParser, $wgContLang, $wgUser; |
2007 | | - $user = is_null( $user ) ? $wgUser : $user; |
2008 | | - // @TODO fixme: check $user->getId() here??? |
2009 | | - if ( $this->mPreparedEdit |
2010 | | - && $this->mPreparedEdit->newText == $text |
2011 | | - && $this->mPreparedEdit->revid == $revid |
2012 | | - ) { |
2013 | | - // Already prepared |
2014 | | - return $this->mPreparedEdit; |
2015 | | - } |
2016 | | - |
2017 | | - $popts = ParserOptions::newFromUserAndLang( $user, $wgContLang ); |
2018 | | - wfRunHooks( 'ArticlePrepareTextForEdit', array( $this, $popts ) ); |
2019 | | - |
2020 | | - $edit = (object)array(); |
2021 | | - $edit->revid = $revid; |
2022 | | - $edit->newText = $text; |
2023 | | - $edit->pst = $wgParser->preSaveTransform( $text, $this->mTitle, $user, $popts ); |
2024 | | - $edit->popts = $this->makeParserOptions( 'canonical' ); |
2025 | | - $edit->output = $wgParser->parse( $edit->pst, $this->mTitle, $edit->popts, true, true, $revid ); |
2026 | | - $edit->oldText = $this->getRawText(); |
2027 | | - |
2028 | | - $this->mPreparedEdit = $edit; |
2029 | | - |
2030 | | - return $edit; |
2031 | | - } |
2032 | | - |
2033 | | - /** |
2034 | | - * Do standard deferred updates after page edit. |
2035 | | - * Update links tables, site stats, search index and message cache. |
2036 | | - * Purges pages that include this page if the text was changed here. |
2037 | | - * Every 100th edit, prune the recent changes table. |
2038 | | - * |
2039 | | - * @private |
2040 | | - * @param $revision Revision object |
2041 | | - * @param $user User object that did the revision |
2042 | | - * @param $options Array of options, following indexes are used: |
2043 | | - * - changed: boolean, whether the revision changed the content (default true) |
2044 | | - * - created: boolean, whether the revision created the page (default false) |
2045 | | - * - oldcountable: boolean or null (default null): |
2046 | | - * - boolean: whether the page was counted as an article before that |
2047 | | - * revision, only used in changed is true and created is false |
2048 | | - * - null: don't change the article count |
2049 | | - */ |
2050 | | - public function doEditUpdates( Revision $revision, User $user, array $options = array() ) { |
2051 | | - global $wgEnableParserCache; |
2052 | | - |
2053 | | - wfProfileIn( __METHOD__ ); |
2054 | | - |
2055 | | - $options += array( 'changed' => true, 'created' => false, 'oldcountable' => null ); |
2056 | | - $text = $revision->getText(); |
2057 | | - |
2058 | | - # Parse the text |
2059 | | - # Be careful not to double-PST: $text is usually already PST-ed once |
2060 | | - if ( !$this->mPreparedEdit || $this->mPreparedEdit->output->getFlag( 'vary-revision' ) ) { |
2061 | | - wfDebug( __METHOD__ . ": No prepared edit or vary-revision is set...\n" ); |
2062 | | - $editInfo = $this->prepareTextForEdit( $text, $revision->getId(), $user ); |
2063 | | - } else { |
2064 | | - wfDebug( __METHOD__ . ": No vary-revision, using prepared edit...\n" ); |
2065 | | - $editInfo = $this->mPreparedEdit; |
2066 | | - } |
2067 | | - |
2068 | | - # Save it to the parser cache |
2069 | | - if ( $wgEnableParserCache ) { |
2070 | | - $parserCache = ParserCache::singleton(); |
2071 | | - $parserCache->save( $editInfo->output, $this, $editInfo->popts ); |
2072 | | - } |
2073 | | - |
2074 | | - # Update the links tables |
2075 | | - $u = new LinksUpdate( $this->mTitle, $editInfo->output ); |
2076 | | - $u->doUpdate(); |
2077 | | - |
2078 | | - wfRunHooks( 'ArticleEditUpdates', array( &$this, &$editInfo, $options['changed'] ) ); |
2079 | | - |
2080 | | - if ( wfRunHooks( 'ArticleEditUpdatesDeleteFromRecentchanges', array( &$this ) ) ) { |
2081 | | - if ( 0 == mt_rand( 0, 99 ) ) { |
2082 | | - // Flush old entries from the `recentchanges` table; we do this on |
2083 | | - // random requests so as to avoid an increase in writes for no good reason |
2084 | | - global $wgRCMaxAge; |
2085 | | - |
2086 | | - $dbw = wfGetDB( DB_MASTER ); |
2087 | | - $cutoff = $dbw->timestamp( time() - $wgRCMaxAge ); |
2088 | | - $dbw->delete( |
2089 | | - 'recentchanges', |
2090 | | - array( "rc_timestamp < '$cutoff'" ), |
2091 | | - __METHOD__ |
2092 | | - ); |
2093 | | - } |
2094 | | - } |
2095 | | - |
2096 | | - if ( !$this->mTitle->exists() ) { |
2097 | | - wfProfileOut( __METHOD__ ); |
2098 | | - return; |
2099 | | - } |
2100 | | - |
2101 | | - $id = $this->getId(); |
2102 | | - $title = $this->mTitle->getPrefixedDBkey(); |
2103 | | - $shortTitle = $this->mTitle->getDBkey(); |
2104 | | - |
2105 | | - if ( !$options['changed'] ) { |
2106 | | - $good = 0; |
2107 | | - $total = 0; |
2108 | | - } elseif ( $options['created'] ) { |
2109 | | - $good = (int)$this->isCountable( $editInfo ); |
2110 | | - $total = 1; |
2111 | | - } elseif ( $options['oldcountable'] !== null ) { |
2112 | | - $good = (int)$this->isCountable( $editInfo ) - (int)$options['oldcountable']; |
2113 | | - $total = 0; |
2114 | | - } else { |
2115 | | - $good = 0; |
2116 | | - $total = 0; |
2117 | | - } |
2118 | | - |
2119 | | - DeferredUpdates::addUpdate( new SiteStatsUpdate( 0, 1, $good, $total ) ); |
2120 | | - DeferredUpdates::addUpdate( new SearchUpdate( $id, $title, $text ) ); |
2121 | | - |
2122 | | - # If this is another user's talk page, update newtalk. |
2123 | | - # Don't do this if $options['changed'] = false (null-edits) nor if |
2124 | | - # it's a minor edit and the user doesn't want notifications for those. |
2125 | | - if ( $options['changed'] |
2126 | | - && $this->mTitle->getNamespace() == NS_USER_TALK |
2127 | | - && $shortTitle != $user->getTitleKey() |
2128 | | - && !( $revision->isMinor() && $user->isAllowed( 'nominornewtalk' ) ) |
2129 | | - ) { |
2130 | | - if ( wfRunHooks( 'ArticleEditUpdateNewTalk', array( &$this ) ) ) { |
2131 | | - $other = User::newFromName( $shortTitle, false ); |
2132 | | - if ( !$other ) { |
2133 | | - wfDebug( __METHOD__ . ": invalid username\n" ); |
2134 | | - } elseif ( User::isIP( $shortTitle ) ) { |
2135 | | - // An anonymous user |
2136 | | - $other->setNewtalk( true ); |
2137 | | - } elseif ( $other->isLoggedIn() ) { |
2138 | | - $other->setNewtalk( true ); |
2139 | | - } else { |
2140 | | - wfDebug( __METHOD__ . ": don't need to notify a nonexistent user\n" ); |
2141 | | - } |
2142 | | - } |
2143 | | - } |
2144 | | - |
2145 | | - if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) { |
2146 | | - MessageCache::singleton()->replace( $shortTitle, $text ); |
2147 | | - } |
2148 | | - |
2149 | | - if( $options['created'] ) { |
2150 | | - self::onArticleCreate( $this->mTitle ); |
2151 | | - } else { |
2152 | | - self::onArticleEdit( $this->mTitle ); |
2153 | | - } |
2154 | | - |
2155 | | - wfProfileOut( __METHOD__ ); |
2156 | | - } |
2157 | | - |
2158 | | - /** |
2159 | | - * Perform article updates on a special page creation. |
2160 | | - * |
2161 | | - * @param $rev Revision object |
2162 | | - * |
2163 | | - * @todo This is a shitty interface function. Kill it and replace the |
2164 | | - * other shitty functions like doEditUpdates and such so it's not needed |
2165 | | - * anymore. |
2166 | | - * @deprecated since 1.18, use doEditUpdates() |
2167 | | - */ |
2168 | | - public function createUpdates( $rev ) { |
2169 | | - wfDeprecated( __METHOD__, '1.18' ); |
2170 | | - global $wgUser; |
2171 | | - $this->doEditUpdates( $rev, $wgUser, array( 'created' => true ) ); |
2172 | | - } |
2173 | | - |
2174 | | - /** |
2175 | | - * This function is called right before saving the wikitext, |
2176 | | - * so we can do things like signatures and links-in-context. |
2177 | | - * |
2178 | | - * @deprecated in 1.19; use Parser::preSaveTransform() instead |
2179 | | - * @param $text String article contents |
2180 | | - * @param $user User object: user doing the edit |
2181 | | - * @param $popts ParserOptions object: parser options, default options for |
2182 | | - * the user loaded if null given |
2183 | | - * @return string article contents with altered wikitext markup (signatures |
2184 | | - * converted, {{subst:}}, templates, etc.) |
2185 | | - */ |
2186 | | - public function preSaveTransform( $text, User $user = null, ParserOptions $popts = null ) { |
2187 | | - global $wgParser, $wgUser; |
2188 | | - |
2189 | | - wfDeprecated( __METHOD__, '1.19' ); |
2190 | | - |
2191 | | - $user = is_null( $user ) ? $wgUser : $user; |
2192 | | - |
2193 | | - if ( $popts === null ) { |
2194 | | - $popts = ParserOptions::newFromUser( $user ); |
2195 | | - } |
2196 | | - |
2197 | | - return $wgParser->preSaveTransform( $text, $this->mTitle, $user, $popts ); |
2198 | | - } |
2199 | | - |
2200 | | - /** |
2201 | | - * Loads page_touched and returns a value indicating if it should be used |
2202 | | - * @return boolean true if not a redirect |
2203 | | - */ |
2204 | | - public function checkTouched() { |
2205 | | - if ( !$this->mDataLoaded ) { |
2206 | | - $this->loadPageData(); |
2207 | | - } |
2208 | | - return !$this->mIsRedirect; |
2209 | | - } |
2210 | | - |
2211 | | - /** |
2212 | | - * Get the page_touched field |
2213 | | - * @return string containing GMT timestamp |
2214 | | - */ |
2215 | | - public function getTouched() { |
2216 | | - if ( !$this->mDataLoaded ) { |
2217 | | - $this->loadPageData(); |
2218 | | - } |
2219 | | - return $this->mTouched; |
2220 | | - } |
2221 | | - |
2222 | | - /** |
2223 | | - * Get the page_latest field |
2224 | | - * @return integer rev_id of current revision |
2225 | | - */ |
2226 | | - public function getLatest() { |
2227 | | - if ( !$this->mDataLoaded ) { |
2228 | | - $this->loadPageData(); |
2229 | | - } |
2230 | | - return (int)$this->mLatest; |
2231 | | - } |
2232 | | - |
2233 | | - /** |
2234 | | - * Edit an article without doing all that other stuff |
2235 | | - * The article must already exist; link tables etc |
2236 | | - * are not updated, caches are not flushed. |
2237 | | - * |
2238 | | - * @param $text String: text submitted |
2239 | | - * @param $user User The relevant user |
2240 | | - * @param $comment String: comment submitted |
2241 | | - * @param $minor Boolean: whereas it's a minor modification |
2242 | | - */ |
2243 | | - public function doQuickEdit( $text, User $user, $comment = '', $minor = 0 ) { |
2244 | | - wfProfileIn( __METHOD__ ); |
2245 | | - |
2246 | | - $dbw = wfGetDB( DB_MASTER ); |
2247 | | - $revision = new Revision( array( |
2248 | | - 'page' => $this->getId(), |
2249 | | - 'text' => $text, |
2250 | | - 'comment' => $comment, |
2251 | | - 'minor_edit' => $minor ? 1 : 0, |
2252 | | - ) ); |
2253 | | - $revision->insertOn( $dbw ); |
2254 | | - $this->updateRevisionOn( $dbw, $revision ); |
2255 | | - |
2256 | | - wfRunHooks( 'NewRevisionFromEditComplete', array( $this, $revision, false, $user ) ); |
2257 | | - |
2258 | | - wfProfileOut( __METHOD__ ); |
2259 | | - } |
2260 | | - |
2261 | | - /** |
2262 | 2215 | * The onArticle*() functions are supposed to be a kind of hooks |
2263 | 2216 | * which should be called whenever any of the specified actions |
2264 | 2217 | * are done. |
— | — | @@ -2561,23 +2514,6 @@ |
2562 | 2515 | } |
2563 | 2516 | |
2564 | 2517 | /** |
2565 | | - * Get parser options suitable for rendering the primary article wikitext |
2566 | | - * @param User|string $user User object or 'canonical' |
2567 | | - * @return ParserOptions |
2568 | | - */ |
2569 | | - public function makeParserOptions( $user ) { |
2570 | | - global $wgContLang; |
2571 | | - if ( $user instanceof User ) { // settings per user (even anons) |
2572 | | - $options = ParserOptions::newFromUser( $user ); |
2573 | | - } else { // canonical settings |
2574 | | - $options = ParserOptions::newFromUserAndLang( new User, $wgContLang ); |
2575 | | - } |
2576 | | - $options->enableLimitReport(); // show inclusion/loop reports |
2577 | | - $options->setTidy( true ); // fix bad HTML |
2578 | | - return $options; |
2579 | | - } |
2580 | | - |
2581 | | - /** |
2582 | 2518 | * Update all the appropriate counts in the category table, given that |
2583 | 2519 | * we've added the categories $added and deleted the categories $deleted. |
2584 | 2520 | * |
— | — | @@ -2692,6 +2628,70 @@ |
2693 | 2629 | } |
2694 | 2630 | |
2695 | 2631 | /** |
| 2632 | + * Perform article updates on a special page creation. |
| 2633 | + * |
| 2634 | + * @param $rev Revision object |
| 2635 | + * |
| 2636 | + * @todo This is a shitty interface function. Kill it and replace the |
| 2637 | + * other shitty functions like doEditUpdates and such so it's not needed |
| 2638 | + * anymore. |
| 2639 | + * @deprecated since 1.18, use doEditUpdates() |
| 2640 | + */ |
| 2641 | + public function createUpdates( $rev ) { |
| 2642 | + wfDeprecated( __METHOD__, '1.18' ); |
| 2643 | + global $wgUser; |
| 2644 | + $this->doEditUpdates( $rev, $wgUser, array( 'created' => true ) ); |
| 2645 | + } |
| 2646 | + |
| 2647 | + /** |
| 2648 | + * This function is called right before saving the wikitext, |
| 2649 | + * so we can do things like signatures and links-in-context. |
| 2650 | + * |
| 2651 | + * @deprecated in 1.19; use Parser::preSaveTransform() instead |
| 2652 | + * @param $text String article contents |
| 2653 | + * @param $user User object: user doing the edit |
| 2654 | + * @param $popts ParserOptions object: parser options, default options for |
| 2655 | + * the user loaded if null given |
| 2656 | + * @return string article contents with altered wikitext markup (signatures |
| 2657 | + * converted, {{subst:}}, templates, etc.) |
| 2658 | + */ |
| 2659 | + public function preSaveTransform( $text, User $user = null, ParserOptions $popts = null ) { |
| 2660 | + global $wgParser, $wgUser; |
| 2661 | + |
| 2662 | + wfDeprecated( __METHOD__, '1.19' ); |
| 2663 | + |
| 2664 | + $user = is_null( $user ) ? $wgUser : $user; |
| 2665 | + |
| 2666 | + if ( $popts === null ) { |
| 2667 | + $popts = ParserOptions::newFromUser( $user ); |
| 2668 | + } |
| 2669 | + |
| 2670 | + return $wgParser->preSaveTransform( $text, $this->mTitle, $user, $popts ); |
| 2671 | + } |
| 2672 | + |
| 2673 | + /** |
| 2674 | + * Check whether the number of revisions of this page surpasses $wgDeleteRevisionsLimit |
| 2675 | + * |
| 2676 | + * @deprecated in 1.19; use Title::isBigDeletion() instead. |
| 2677 | + * @return bool |
| 2678 | + */ |
| 2679 | + public function isBigDeletion() { |
| 2680 | + wfDeprecated( __METHOD__, '1.19' ); |
| 2681 | + return $this->mTitle->isBigDeletion(); |
| 2682 | + } |
| 2683 | + |
| 2684 | + /** |
| 2685 | + * Get the approximate revision count of this page. |
| 2686 | + * |
| 2687 | + * @deprecated in 1.19; use Title::estimateRevisionCount() instead. |
| 2688 | + * @return int |
| 2689 | + */ |
| 2690 | + public function estimateRevisionCount() { |
| 2691 | + wfDeprecated( __METHOD__, '1.19' ); |
| 2692 | + return $this->mTitle->estimateRevisionCount(); |
| 2693 | + } |
| 2694 | + |
| 2695 | + /** |
2696 | 2696 | * Update the article's restriction field, and leave a log entry. |
2697 | 2697 | * |
2698 | 2698 | * @deprecated since 1.19 |