r92991 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r92990‎ | r92991 | r92992 >
Date:17:44, 24 July 2011
Author:reedy
Status:deferred
Tags:
Comment:
Revert r92990
Modified paths:
  • /branches/iwtransclusion/phase3v3/includes/Article.php (modified) (history)
  • /branches/iwtransclusion/phase3v3/includes/EditPage.php (modified) (history)
  • /branches/iwtransclusion/phase3v3/includes/Linker.php (modified) (history)
  • /branches/iwtransclusion/phase3v3/includes/OutputPage.php (modified) (history)
  • /branches/iwtransclusion/phase3v3/includes/Title.php (modified) (history)
  • /branches/iwtransclusion/phase3v3/includes/db/Database.php (modified) (history)
  • /branches/iwtransclusion/phase3v3/includes/parser/Parser.php (modified) (history)
  • /branches/iwtransclusion/phase3v3/includes/parser/ParserOutput.php (modified) (history)
  • /branches/iwtransclusion/phase3v3/languages/messages/MessagesEn.php (modified) (history)
  • /branches/iwtransclusion/phase3v3/maintenance/archives/patch-globaltemplatelinks.sql (modified) (history)
  • /branches/iwtransclusion/phase3v3/maintenance/language/messages.inc (modified) (history)

Diff [purge]

Index: branches/iwtransclusion/phase3v3/maintenance/archives/patch-globaltemplatelinks.sql
@@ -17,19 +17,15 @@
1818 -- Needed for display purposes
1919 gtl_from_title varchar(255) binary NOT NULL,
2020
21 - -- The interwiki prefix of the wiki that hosts the transcluded page
22 - gtl_to_prefix varchar(32) NOT NULL,
 21+ -- The wiki ID of the wiki that hosts the transcluded page
 22+ gtl_to_wiki varchar(64) NOT NULL,
2323
2424 -- The namespace of the transcluded page on that wiki
2525 gtl_to_namespace int NOT NULL,
2626
27 - -- The namespace name of transcluded page
28 - -- Needed for display purposes, since the local namespace ID doesn't necessarily match a distant one
29 - gtl_to_namespacetext varchar(255) NOT NULL,
30 -
3127 -- The title of the transcluded page on that wiki
3228 gtl_to_title varchar(255) binary NOT NULL
3329 ) /*$wgDBTableOptions*/;
3430
35 -CREATE UNIQUE INDEX /*i*/gtl_to_from ON /*_*/globaltemplatelinks (gtl_to_prefix, gtl_to_namespace, gtl_to_title, gtl_from_wiki, gtl_from_page);
36 -CREATE UNIQUE INDEX /*i*/gtl_from_to ON /*_*/globaltemplatelinks (gtl_from_wiki, gtl_from_page, gtl_to_prefix, gtl_to_namespace, gtl_to_title);
 31+CREATE UNIQUE INDEX /*i*/gtl_to_from ON /*_*/globaltemplatelinks (gtl_to_wiki, gtl_to_namespace, gtl_to_title, gtl_from_wiki, gtl_from_page);
 32+CREATE UNIQUE INDEX /*i*/gtl_from_to ON /*_*/globaltemplatelinks (gtl_from_wiki, gtl_from_page, gtl_to_wiki, gtl_to_namespace, gtl_to_title);
Index: branches/iwtransclusion/phase3v3/maintenance/language/messages.inc
@@ -639,9 +639,6 @@
640640 'templatesused',
641641 'templatesusedpreview',
642642 'templatesusedsection',
643 - 'distanttemplatesused',
644 - 'distanttemplatesusedpreview',
645 - 'distanttemplatesusedsection',
646643 'template-protected',
647644 'template-semiprotected',
648645 'hiddencategories',
Index: branches/iwtransclusion/phase3v3/includes/Article.php
@@ -1627,594 +1627,6 @@
16281628 }
16291629
16301630 /**
1631 - * Back-end article deletion
1632 - * Deletes the article with database consistency, writes logs, purges caches
1633 - *
1634 - * @param $reason string delete reason for deletion log
1635 - * @param suppress bitfield
1636 - * Revision::DELETED_TEXT
1637 - * Revision::DELETED_COMMENT
1638 - * Revision::DELETED_USER
1639 - * Revision::DELETED_RESTRICTED
1640 - * @param $id int article ID
1641 - * @param $commit boolean defaults to true, triggers transaction end
1642 - * @return boolean true if successful
1643 - */
1644 - public function doDeleteArticle( $reason, $suppress = false, $id = 0, $commit = true ) {
1645 - global $wgDeferredUpdateList, $wgUseTrackbacks, $wgEnableInterwikiTemplatesTracking, $wgGlobalDatabase;
1646 -
1647 - wfDebug( __METHOD__ . "\n" );
1648 -
1649 - if ( ! wfRunHooks( 'ArticleDelete', array( &$this, &$wgUser, &$reason, &$error ) ) ) {
1650 - return false;
1651 - }
1652 - $dbw = wfGetDB( DB_MASTER );
1653 - $t = $this->mTitle->getDBkey();
1654 - $id = $id ? $id : $this->mTitle->getArticleID( Title::GAID_FOR_UPDATE );
1655 -
1656 - if ( $t === '' || $id == 0 ) {
1657 - return false;
1658 - }
1659 -
1660 - $u = new SiteStatsUpdate( 0, 1, - (int)$this->isCountable( $this->getRawText() ), -1 );
1661 - array_push( $wgDeferredUpdateList, $u );
1662 -
1663 - // Bitfields to further suppress the content
1664 - if ( $suppress ) {
1665 - $bitfield = 0;
1666 - // This should be 15...
1667 - $bitfield |= Revision::DELETED_TEXT;
1668 - $bitfield |= Revision::DELETED_COMMENT;
1669 - $bitfield |= Revision::DELETED_USER;
1670 - $bitfield |= Revision::DELETED_RESTRICTED;
1671 - } else {
1672 - $bitfield = 'rev_deleted';
1673 - }
1674 -
1675 - $dbw->begin();
1676 - // For now, shunt the revision data into the archive table.
1677 - // Text is *not* removed from the text table; bulk storage
1678 - // is left intact to avoid breaking block-compression or
1679 - // immutable storage schemes.
1680 - //
1681 - // For backwards compatibility, note that some older archive
1682 - // table entries will have ar_text and ar_flags fields still.
1683 - //
1684 - // In the future, we may keep revisions and mark them with
1685 - // the rev_deleted field, which is reserved for this purpose.
1686 - $dbw->insertSelect( 'archive', array( 'page', 'revision' ),
1687 - array(
1688 - 'ar_namespace' => 'page_namespace',
1689 - 'ar_title' => 'page_title',
1690 - 'ar_comment' => 'rev_comment',
1691 - 'ar_user' => 'rev_user',
1692 - 'ar_user_text' => 'rev_user_text',
1693 - 'ar_timestamp' => 'rev_timestamp',
1694 - 'ar_minor_edit' => 'rev_minor_edit',
1695 - 'ar_rev_id' => 'rev_id',
1696 - 'ar_text_id' => 'rev_text_id',
1697 - 'ar_text' => '\'\'', // Be explicit to appease
1698 - 'ar_flags' => '\'\'', // MySQL's "strict mode"...
1699 - 'ar_len' => 'rev_len',
1700 - 'ar_page_id' => 'page_id',
1701 - 'ar_deleted' => $bitfield
1702 - ), array(
1703 - 'page_id' => $id,
1704 - 'page_id = rev_page'
1705 - ), __METHOD__
1706 - );
1707 -
1708 - # Delete restrictions for it
1709 - $dbw->delete( 'page_restrictions', array ( 'pr_page' => $id ), __METHOD__ );
1710 -
1711 - # Now that it's safely backed up, delete it
1712 - $dbw->delete( 'page', array( 'page_id' => $id ), __METHOD__ );
1713 - $ok = ( $dbw->affectedRows() > 0 ); // getArticleId() uses slave, could be laggy
1714 -
1715 - if ( !$ok ) {
1716 - $dbw->rollback();
1717 - return false;
1718 - }
1719 -
1720 - # Fix category table counts
1721 - $cats = array();
1722 - $res = $dbw->select( 'categorylinks', 'cl_to', array( 'cl_from' => $id ), __METHOD__ );
1723 -
1724 - foreach ( $res as $row ) {
1725 - $cats [] = $row->cl_to;
1726 - }
1727 -
1728 - $this->updateCategoryCounts( array(), $cats );
1729 -
1730 - # If using cascading deletes, we can skip some explicit deletes
1731 - if ( !$dbw->cascadingDeletes() ) {
1732 - $dbw->delete( 'revision', array( 'rev_page' => $id ), __METHOD__ );
1733 -
1734 - if ( $wgUseTrackbacks )
1735 - $dbw->delete( 'trackbacks', array( 'tb_page' => $id ), __METHOD__ );
1736 -
1737 - # Delete outgoing links
1738 - $dbw->delete( 'pagelinks', array( 'pl_from' => $id ) );
1739 - $dbw->delete( 'imagelinks', array( 'il_from' => $id ) );
1740 - $dbw->delete( 'categorylinks', array( 'cl_from' => $id ) );
1741 - $dbw->delete( 'templatelinks', array( 'tl_from' => $id ) );
1742 - $dbw->delete( 'externallinks', array( 'el_from' => $id ) );
1743 - $dbw->delete( 'langlinks', array( 'll_from' => $id ) );
1744 - $dbw->delete( 'iwlinks', array( 'iwl_from' => $id ) );
1745 - $dbw->delete( 'redirect', array( 'rd_from' => $id ) );
1746 -
1747 - if ( $wgEnableInterwikiTemplatesTracking && $wgGlobalDatabase ) {
1748 - $dbw2 = wfGetDB( DB_MASTER, array(), $wgGlobalDatabase );
1749 - $dbw2->delete( 'globaltemplatelinks',
1750 - array( 'gtl_from_wiki' => wfWikiID( ),
1751 - 'gtl_from_page' => $id )
1752 - );
1753 - }
1754 - }
1755 -
1756 - # If using cleanup triggers, we can skip some manual deletes
1757 - if ( !$dbw->cleanupTriggers() ) {
1758 - # Clean up recentchanges entries...
1759 - $dbw->delete( 'recentchanges',
1760 - array( 'rc_type != ' . RC_LOG,
1761 - 'rc_namespace' => $this->mTitle->getNamespace(),
1762 - 'rc_title' => $this->mTitle->getDBkey() ),
1763 - __METHOD__ );
1764 - $dbw->delete( 'recentchanges',
1765 - array( 'rc_type != ' . RC_LOG, 'rc_cur_id' => $id ),
1766 - __METHOD__ );
1767 - }
1768 -
1769 - # Clear caches
1770 - Article::onArticleDelete( $this->mTitle );
1771 -
1772 - # Clear the cached article id so the interface doesn't act like we exist
1773 - $this->mTitle->resetArticleID( 0 );
1774 -
1775 - # Log the deletion, if the page was suppressed, log it at Oversight instead
1776 - $logtype = $suppress ? 'suppress' : 'delete';
1777 - $log = new LogPage( $logtype );
1778 -
1779 - # Make sure logging got through
1780 - $log->addEntry( 'delete', $this->mTitle, $reason, array() );
1781 -
1782 - if ( $commit ) {
1783 - $dbw->commit();
1784 - }
1785 -
1786 - wfRunHooks( 'ArticleDeleteComplete', array( &$this, &$wgUser, $reason, $id ) );
1787 - return true;
1788 - }
1789 -
1790 - /**
1791 - * Roll back the most recent consecutive set of edits to a page
1792 - * from the same user; fails if there are no eligible edits to
1793 - * roll back to, e.g. user is the sole contributor. This function
1794 - * performs permissions checks on $wgUser, then calls commitRollback()
1795 - * to do the dirty work
1796 - *
1797 - * @param $fromP String: Name of the user whose edits to rollback.
1798 - * @param $summary String: Custom summary. Set to default summary if empty.
1799 - * @param $token String: Rollback token.
1800 - * @param $bot Boolean: If true, mark all reverted edits as bot.
1801 - *
1802 - * @param $resultDetails Array: contains result-specific array of additional values
1803 - * 'alreadyrolled' : 'current' (rev)
1804 - * success : 'summary' (str), 'current' (rev), 'target' (rev)
1805 - *
1806 - * @return array of errors, each error formatted as
1807 - * array(messagekey, param1, param2, ...).
1808 - * On success, the array is empty. This array can also be passed to
1809 - * OutputPage::showPermissionsErrorPage().
1810 - */
1811 - public function doRollback( $fromP, $summary, $token, $bot, &$resultDetails ) {
1812 - global $wgUser;
1813 -
1814 - $resultDetails = null;
1815 -
1816 - # Check permissions
1817 - $editErrors = $this->mTitle->getUserPermissionsErrors( 'edit', $wgUser );
1818 - $rollbackErrors = $this->mTitle->getUserPermissionsErrors( 'rollback', $wgUser );
1819 - $errors = array_merge( $editErrors, wfArrayDiff2( $rollbackErrors, $editErrors ) );
1820 -
1821 - if ( !$wgUser->matchEditToken( $token, array( $this->mTitle->getPrefixedText(), $fromP ) ) ) {
1822 - $errors[] = array( 'sessionfailure' );
1823 - }
1824 -
1825 - if ( $wgUser->pingLimiter( 'rollback' ) || $wgUser->pingLimiter() ) {
1826 - $errors[] = array( 'actionthrottledtext' );
1827 - }
1828 -
1829 - # If there were errors, bail out now
1830 - if ( !empty( $errors ) ) {
1831 - return $errors;
1832 - }
1833 -
1834 - return $this->commitRollback( $fromP, $summary, $bot, $resultDetails );
1835 - }
1836 -
1837 - /**
1838 - * Backend implementation of doRollback(), please refer there for parameter
1839 - * and return value documentation
1840 - *
1841 - * NOTE: This function does NOT check ANY permissions, it just commits the
1842 - * rollback to the DB Therefore, you should only call this function direct-
1843 - * ly if you want to use custom permissions checks. If you don't, use
1844 - * doRollback() instead.
1845 - */
1846 - public function commitRollback( $fromP, $summary, $bot, &$resultDetails ) {
1847 - global $wgUseRCPatrol, $wgUser, $wgLang;
1848 -
1849 - $dbw = wfGetDB( DB_MASTER );
1850 -
1851 - if ( wfReadOnly() ) {
1852 - return array( array( 'readonlytext' ) );
1853 - }
1854 -
1855 - # Get the last editor
1856 - $current = Revision::newFromTitle( $this->mTitle );
1857 - if ( is_null( $current ) ) {
1858 - # Something wrong... no page?
1859 - return array( array( 'notanarticle' ) );
1860 - }
1861 -
1862 - $from = str_replace( '_', ' ', $fromP );
1863 - # User name given should match up with the top revision.
1864 - # If the user was deleted then $from should be empty.
1865 - if ( $from != $current->getUserText() ) {
1866 - $resultDetails = array( 'current' => $current );
1867 - return array( array( 'alreadyrolled',
1868 - htmlspecialchars( $this->mTitle->getPrefixedText() ),
1869 - htmlspecialchars( $fromP ),
1870 - htmlspecialchars( $current->getUserText() )
1871 - ) );
1872 - }
1873 -
1874 - # Get the last edit not by this guy...
1875 - # Note: these may not be public values
1876 - $user = intval( $current->getRawUser() );
1877 - $user_text = $dbw->addQuotes( $current->getRawUserText() );
1878 - $s = $dbw->selectRow( 'revision',
1879 - array( 'rev_id', 'rev_timestamp', 'rev_deleted' ),
1880 - array( 'rev_page' => $current->getPage(),
1881 - "rev_user != {$user} OR rev_user_text != {$user_text}"
1882 - ), __METHOD__,
1883 - array( 'USE INDEX' => 'page_timestamp',
1884 - 'ORDER BY' => 'rev_timestamp DESC' )
1885 - );
1886 - if ( $s === false ) {
1887 - # No one else ever edited this page
1888 - return array( array( 'cantrollback' ) );
1889 - } else if ( $s->rev_deleted & Revision::DELETED_TEXT || $s->rev_deleted & Revision::DELETED_USER ) {
1890 - # Only admins can see this text
1891 - return array( array( 'notvisiblerev' ) );
1892 - }
1893 -
1894 - $set = array();
1895 - if ( $bot && $wgUser->isAllowed( 'markbotedits' ) ) {
1896 - # Mark all reverted edits as bot
1897 - $set['rc_bot'] = 1;
1898 - }
1899 -
1900 - if ( $wgUseRCPatrol ) {
1901 - # Mark all reverted edits as patrolled
1902 - $set['rc_patrolled'] = 1;
1903 - }
1904 -
1905 - if ( count( $set ) ) {
1906 - $dbw->update( 'recentchanges', $set,
1907 - array( /* WHERE */
1908 - 'rc_cur_id' => $current->getPage(),
1909 - 'rc_user_text' => $current->getUserText(),
1910 - "rc_timestamp > '{$s->rev_timestamp}'",
1911 - ), __METHOD__
1912 - );
1913 - }
1914 -
1915 - # Generate the edit summary if necessary
1916 - $target = Revision::newFromId( $s->rev_id );
1917 - if ( empty( $summary ) ) {
1918 - if ( $from == '' ) { // no public user name
1919 - $summary = wfMsgForContent( 'revertpage-nouser' );
1920 - } else {
1921 - $summary = wfMsgForContent( 'revertpage' );
1922 - }
1923 - }
1924 -
1925 - # Allow the custom summary to use the same args as the default message
1926 - $args = array(
1927 - $target->getUserText(), $from, $s->rev_id,
1928 - $wgLang->timeanddate( wfTimestamp( TS_MW, $s->rev_timestamp ), true ),
1929 - $current->getId(), $wgLang->timeanddate( $current->getTimestamp() )
1930 - );
1931 - $summary = wfMsgReplaceArgs( $summary, $args );
1932 -
1933 - # Save
1934 - $flags = EDIT_UPDATE;
1935 -
1936 - if ( $wgUser->isAllowed( 'minoredit' ) ) {
1937 - $flags |= EDIT_MINOR;
1938 - }
1939 -
1940 - if ( $bot && ( $wgUser->isAllowedAny( 'markbotedits', 'bot' ) ) ) {
1941 - $flags |= EDIT_FORCE_BOT;
1942 - }
1943 -
1944 - # Actually store the edit
1945 - $status = $this->doEdit( $target->getText(), $summary, $flags, $target->getId() );
1946 - if ( !empty( $status->value['revision'] ) ) {
1947 - $revId = $status->value['revision']->getId();
1948 - } else {
1949 - $revId = false;
1950 - }
1951 -
1952 - wfRunHooks( 'ArticleRollbackComplete', array( $this, $wgUser, $target, $current ) );
1953 -
1954 - $resultDetails = array(
1955 - 'summary' => $summary,
1956 - 'current' => $current,
1957 - 'target' => $target,
1958 - 'newid' => $revId
1959 - );
1960 -
1961 - return array();
1962 - }
1963 -
1964 - /**
1965 - * User interface for rollback operations
1966 - */
1967 - public function rollback() {
1968 - global $wgUser, $wgOut, $wgRequest;
1969 -
1970 - $details = null;
1971 -
1972 - $result = $this->doRollback(
1973 - $wgRequest->getVal( 'from' ),
1974 - $wgRequest->getText( 'summary' ),
1975 - $wgRequest->getVal( 'token' ),
1976 - $wgRequest->getBool( 'bot' ),
1977 - $details
1978 - );
1979 -
1980 - if ( in_array( array( 'actionthrottledtext' ), $result ) ) {
1981 - $wgOut->rateLimited();
1982 - return;
1983 - }
1984 -
1985 - if ( isset( $result[0][0] ) && ( $result[0][0] == 'alreadyrolled' || $result[0][0] == 'cantrollback' ) ) {
1986 - $wgOut->setPageTitle( wfMsg( 'rollbackfailed' ) );
1987 - $errArray = $result[0];
1988 - $errMsg = array_shift( $errArray );
1989 - $wgOut->addWikiMsgArray( $errMsg, $errArray );
1990 -
1991 - if ( isset( $details['current'] ) ) {
1992 - $current = $details['current'];
1993 -
1994 - if ( $current->getComment() != '' ) {
1995 - $wgOut->addWikiMsgArray( 'editcomment', array(
1996 - Linker::formatComment( $current->getComment() ) ), array( 'replaceafter' ) );
1997 - }
1998 - }
1999 -
2000 - return;
2001 - }
2002 -
2003 - # Display permissions errors before read-only message -- there's no
2004 - # point in misleading the user into thinking the inability to rollback
2005 - # is only temporary.
2006 - if ( !empty( $result ) && $result !== array( array( 'readonlytext' ) ) ) {
2007 - # array_diff is completely broken for arrays of arrays, sigh.
2008 - # Remove any 'readonlytext' error manually.
2009 - $out = array();
2010 - foreach ( $result as $error ) {
2011 - if ( $error != array( 'readonlytext' ) ) {
2012 - $out [] = $error;
2013 - }
2014 - }
2015 - $wgOut->showPermissionsErrorPage( $out );
2016 -
2017 - return;
2018 - }
2019 -
2020 - if ( $result == array( array( 'readonlytext' ) ) ) {
2021 - $wgOut->readOnlyPage();
2022 -
2023 - return;
2024 - }
2025 -
2026 - $current = $details['current'];
2027 - $target = $details['target'];
2028 - $newId = $details['newid'];
2029 - $wgOut->setPageTitle( wfMsg( 'actioncomplete' ) );
2030 - $wgOut->setRobotPolicy( 'noindex,nofollow' );
2031 -
2032 - if ( $current->getUserText() === '' ) {
2033 - $old = wfMsg( 'rev-deleted-user' );
2034 - } else {
2035 - $old = Linker::userLink( $current->getUser(), $current->getUserText() )
2036 - . Linker::userToolLinks( $current->getUser(), $current->getUserText() );
2037 - }
2038 -
2039 - $new = Linker::userLink( $target->getUser(), $target->getUserText() )
2040 - . Linker::userToolLinks( $target->getUser(), $target->getUserText() );
2041 - $wgOut->addHTML( wfMsgExt( 'rollback-success', array( 'parse', 'replaceafter' ), $old, $new ) );
2042 - $wgOut->returnToMain( false, $this->mTitle );
2043 -
2044 - if ( !$wgRequest->getBool( 'hidediff', false ) && !$wgUser->getBoolOption( 'norollbackdiff', false ) ) {
2045 - $de = new DifferenceEngine( $this->mTitle, $current->getId(), $newId, false, true );
2046 - $de->showDiff( '', '' );
2047 - }
2048 - }
2049 -
2050 - /**
2051 - * Do standard deferred updates after page view
2052 - */
2053 - public function viewUpdates() {
2054 - global $wgDeferredUpdateList, $wgDisableCounters, $wgUser;
2055 - if ( wfReadOnly() ) {
2056 - return;
2057 - }
2058 -
2059 - # Don't update page view counters on views from bot users (bug 14044)
2060 - if ( !$wgDisableCounters && !$wgUser->isAllowed( 'bot' ) && $this->getID() ) {
2061 - $wgDeferredUpdateList[] = new ViewCountUpdate( $this->getID() );
2062 - $wgDeferredUpdateList[] = new SiteStatsUpdate( 1, 0, 0 );
2063 - }
2064 -
2065 - # Update newtalk / watchlist notification status
2066 - $wgUser->clearNotification( $this->mTitle );
2067 - }
2068 -
2069 - /**
2070 - * Prepare text which is about to be saved.
2071 - * Returns a stdclass with source, pst and output members
2072 - */
2073 - public function prepareTextForEdit( $text, $revid = null, User $user = null ) {
2074 - if ( $this->mPreparedEdit && $this->mPreparedEdit->newText == $text && $this->mPreparedEdit->revid == $revid ) {
2075 - // Already prepared
2076 - return $this->mPreparedEdit;
2077 - }
2078 -
2079 - global $wgParser;
2080 -
2081 - if( $user === null ) {
2082 - global $wgUser;
2083 - $user = $wgUser;
2084 - }
2085 - $popts = ParserOptions::newFromUser( $user );
2086 - wfRunHooks( 'ArticlePrepareTextForEdit', array( $this, $popts ) );
2087 -
2088 - $edit = (object)array();
2089 - $edit->revid = $revid;
2090 - $edit->newText = $text;
2091 - $edit->pst = $this->preSaveTransform( $text, $user, $popts );
2092 - $edit->popts = $this->getParserOptions();
2093 - $edit->output = $wgParser->parse( $edit->pst, $this->mTitle, $edit->popts, true, true, $revid );
2094 - $edit->oldText = $this->getRawText();
2095 -
2096 - $this->mPreparedEdit = $edit;
2097 -
2098 - return $edit;
2099 - }
2100 -
2101 - /**
2102 - * Do standard deferred updates after page edit.
2103 - * Update links tables, site stats, search index and message cache.
2104 - * Purges pages that include this page if the text was changed here.
2105 - * Every 100th edit, prune the recent changes table.
2106 - *
2107 - * @private
2108 - * @param $text String: New text of the article
2109 - * @param $summary String: Edit summary
2110 - * @param $minoredit Boolean: Minor edit
2111 - * @param $timestamp_of_pagechange String timestamp associated with the page change
2112 - * @param $newid Integer: rev_id value of the new revision
2113 - * @param $changed Boolean: Whether or not the content actually changed
2114 - * @param $user User object: User doing the edit
2115 - */
2116 - public function editUpdates( $text, $summary, $minoredit, $timestamp_of_pagechange, $newid, $changed = true, User $user = null ) {
2117 - global $wgDeferredUpdateList, $wgUser, $wgEnableParserCache;
2118 -
2119 - wfProfileIn( __METHOD__ );
2120 -
2121 - # Parse the text
2122 - # Be careful not to double-PST: $text is usually already PST-ed once
2123 - if ( !$this->mPreparedEdit || $this->mPreparedEdit->output->getFlag( 'vary-revision' ) ) {
2124 - wfDebug( __METHOD__ . ": No prepared edit or vary-revision is set...\n" );
2125 - $editInfo = $this->prepareTextForEdit( $text, $newid, $user );
2126 - } else {
2127 - wfDebug( __METHOD__ . ": No vary-revision, using prepared edit...\n" );
2128 - $editInfo = $this->mPreparedEdit;
2129 - }
2130 -
2131 - # Save it to the parser cache
2132 - if ( $wgEnableParserCache ) {
2133 - $parserCache = ParserCache::singleton();
2134 - $parserCache->save( $editInfo->output, $this, $editInfo->popts );
2135 - }
2136 -
2137 - # Update the links tables
2138 - $u = new LinksUpdate( $this->mTitle, $editInfo->output );
2139 - $u->doUpdate();
2140 -
2141 - wfRunHooks( 'ArticleEditUpdates', array( &$this, &$editInfo, $changed ) );
2142 -
2143 - if ( wfRunHooks( 'ArticleEditUpdatesDeleteFromRecentchanges', array( &$this ) ) ) {
2144 - if ( 0 == mt_rand( 0, 99 ) ) {
2145 - // Flush old entries from the `recentchanges` table; we do this on
2146 - // random requests so as to avoid an increase in writes for no good reason
2147 - global $wgRCMaxAge;
2148 -
2149 - $dbw = wfGetDB( DB_MASTER );
2150 - $cutoff = $dbw->timestamp( time() - $wgRCMaxAge );
2151 - $dbw->delete(
2152 - 'recentchanges',
2153 - array( "rc_timestamp < '$cutoff'" ),
2154 - __METHOD__
2155 - );
2156 - }
2157 - }
2158 -
2159 - $id = $this->getID();
2160 - $title = $this->mTitle->getPrefixedDBkey();
2161 - $shortTitle = $this->mTitle->getDBkey();
2162 -
2163 - if ( 0 == $id ) {
2164 - wfProfileOut( __METHOD__ );
2165 - return;
2166 - }
2167 -
2168 - $u = new SiteStatsUpdate( 0, 1, $this->mGoodAdjustment, $this->mTotalAdjustment );
2169 - array_push( $wgDeferredUpdateList, $u );
2170 - $u = new SearchUpdate( $id, $title, $text );
2171 - array_push( $wgDeferredUpdateList, $u );
2172 -
2173 - # If this is another user's talk page, update newtalk
2174 - # Don't do this if $changed = false otherwise some idiot can null-edit a
2175 - # load of user talk pages and piss people off, nor if it's a minor edit
2176 - # by a properly-flagged bot.
2177 - if ( $this->mTitle->getNamespace() == NS_USER_TALK && $shortTitle != $wgUser->getTitleKey() && $changed
2178 - && !( $minoredit && $wgUser->isAllowed( 'nominornewtalk' ) )
2179 - ) {
2180 - if ( wfRunHooks( 'ArticleEditUpdateNewTalk', array( &$this ) ) ) {
2181 - $other = User::newFromName( $shortTitle, false );
2182 - if ( !$other ) {
2183 - wfDebug( __METHOD__ . ": invalid username\n" );
2184 - } elseif ( User::isIP( $shortTitle ) ) {
2185 - // An anonymous user
2186 - $other->setNewtalk( true );
2187 - } elseif ( $other->isLoggedIn() ) {
2188 - $other->setNewtalk( true );
2189 - } else {
2190 - wfDebug( __METHOD__ . ": don't need to notify a nonexistent user\n" );
2191 - }
2192 - }
2193 - }
2194 -
2195 - if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
2196 - MessageCache::singleton()->replace( $shortTitle, $text );
2197 - }
2198 -
2199 - wfProfileOut( __METHOD__ );
2200 - }
2201 -
2202 - /**
2203 - * Perform article updates on a special page creation.
2204 - *
2205 - * @param $rev Revision object
2206 - *
2207 - * @todo This is a shitty interface function. Kill it and replace the
2208 - * other shitty functions like editUpdates and such so it's not needed
2209 - * anymore.
2210 - */
2211 - public function createUpdates( $rev ) {
2212 - $this->mGoodAdjustment = $this->isCountable( $rev->getText() );
2213 - $this->mTotalAdjustment = 1;
2214 - $this->editUpdates( $rev->getText(), $rev->getComment(),
2215 - $rev->isMinor(), wfTimestamp(), $rev->getId(), true );
2216 - }
2217 -
2218 - /**
22191631 * Generate the navigation links when browsing through an article revisions
22201632 * It shows the information as:
22211633 * Revision as of \<date\>; view current revision
@@ -2482,166 +1894,6 @@
24831895 }
24841896
24851897 /**
2486 - * Return a list of templates used by this article.
2487 - * Uses the templatelinks table
2488 - *
2489 - * @return Array of Title objects
2490 - */
2491 - public function getUsedTemplates() {
2492 - $result = array();
2493 - $id = $this->mTitle->getArticleID();
2494 -
2495 - if ( $id == 0 ) {
2496 - return array();
2497 - }
2498 -
2499 - $dbr = wfGetDB( DB_SLAVE );
2500 - $res = $dbr->select( array( 'templatelinks' ),
2501 - array( 'tl_namespace', 'tl_title' ),
2502 - array( 'tl_from' => $id ),
2503 - __METHOD__ );
2504 -
2505 - if ( $res !== false ) {
2506 - foreach ( $res as $row ) {
2507 - $result[] = Title::makeTitle( $row->tl_namespace, $row->tl_title );
2508 - }
2509 - }
2510 -
2511 - return $result;
2512 - }
2513 -
2514 - /**
2515 - * Return a list of distant templates used by this article.
2516 - * Uses the globaltemplatelinks table
2517 - *
2518 - * @return Array of Title objects
2519 - */
2520 - public function getUsedDistantTemplates() {
2521 - global $wgGlobalDatabase;
2522 -
2523 - $result = array();
2524 -
2525 - if ( $wgGlobalDatabase ) {
2526 - $id = $this->mTitle->getArticleID();
2527 -
2528 - if ( $id == 0 ) {
2529 - return array();
2530 - }
2531 -
2532 - $dbr = wfGetDB( DB_SLAVE, array(), $wgGlobalDatabase );
2533 - $res = $dbr->select( array( 'globaltemplatelinks' ),
2534 - array( 'gtl_to_prefix', 'gtl_to_namespace', 'gtl_to_title' ),
2535 - array( 'gtl_from_wiki' => wfWikiID( ), 'gtl_from_page' => $id ),
2536 - __METHOD__ );
2537 -
2538 - if ( $res !== false ) {
2539 - foreach ( $res as $row ) {
2540 - $result[] = Title::makeTitle( $row->gtl_to_namespace, $row->gtl_to_title, null, $row->gtl_to_prefix );
2541 - }
2542 - }
2543 -
2544 - $dbr->freeResult( $res );
2545 - }
2546 -
2547 - return $result;
2548 - }
2549 -
2550 - /**
2551 - * Returns a list of hidden categories this page is a member of.
2552 - * Uses the page_props and categorylinks tables.
2553 - *
2554 - * @return Array of Title objects
2555 - */
2556 - public function getHiddenCategories() {
2557 - $result = array();
2558 - $id = $this->mTitle->getArticleID();
2559 -
2560 - if ( $id == 0 ) {
2561 - return array();
2562 - }
2563 -
2564 - $dbr = wfGetDB( DB_SLAVE );
2565 - $res = $dbr->select( array( 'categorylinks', 'page_props', 'page' ),
2566 - array( 'cl_to' ),
2567 - array( 'cl_from' => $id, 'pp_page=page_id', 'pp_propname' => 'hiddencat',
2568 - 'page_namespace' => NS_CATEGORY, 'page_title=cl_to' ),
2569 - __METHOD__ );
2570 -
2571 - if ( $res !== false ) {
2572 - foreach ( $res as $row ) {
2573 - $result[] = Title::makeTitle( NS_CATEGORY, $row->cl_to );
2574 - }
2575 - }
2576 -
2577 - return $result;
2578 - }
2579 -
2580 - /**
2581 - * Return an applicable autosummary if one exists for the given edit.
2582 - * @param $oldtext String: the previous text of the page.
2583 - * @param $newtext String: The submitted text of the page.
2584 - * @param $flags Int bitmask: a bitmask of flags submitted for the edit.
2585 - * @return string An appropriate autosummary, or an empty string.
2586 - */
2587 - public static function getAutosummary( $oldtext, $newtext, $flags ) {
2588 - global $wgContLang;
2589 -
2590 - # Decide what kind of autosummary is needed.
2591 -
2592 - # Redirect autosummaries
2593 - $ot = Title::newFromRedirect( $oldtext );
2594 - $rt = Title::newFromRedirect( $newtext );
2595 -
2596 - if ( is_object( $rt ) && ( !is_object( $ot ) || !$rt->equals( $ot ) || $ot->getFragment() != $rt->getFragment() ) ) {
2597 - return wfMsgForContent( 'autoredircomment', $rt->getFullText() );
2598 - }
2599 -
2600 - # New page autosummaries
2601 - if ( $flags & EDIT_NEW && strlen( $newtext ) ) {
2602 - # If they're making a new article, give its text, truncated, in the summary.
2603 -
2604 - $truncatedtext = $wgContLang->truncate(
2605 - str_replace( "\n", ' ', $newtext ),
2606 - max( 0, 200 - strlen( wfMsgForContent( 'autosumm-new' ) ) ) );
2607 -
2608 - return wfMsgForContent( 'autosumm-new', $truncatedtext );
2609 - }
2610 -
2611 - # Blanking autosummaries
2612 - if ( $oldtext != '' && $newtext == '' ) {
2613 - return wfMsgForContent( 'autosumm-blank' );
2614 - } elseif ( strlen( $oldtext ) > 10 * strlen( $newtext ) && strlen( $newtext ) < 500 ) {
2615 - # Removing more than 90% of the article
2616 -
2617 - $truncatedtext = $wgContLang->truncate(
2618 - $newtext,
2619 - max( 0, 200 - strlen( wfMsgForContent( 'autosumm-replace' ) ) ) );
2620 -
2621 - return wfMsgForContent( 'autosumm-replace', $truncatedtext );
2622 - }
2623 -
2624 - # If we reach this point, there's no applicable autosummary for our case, so our
2625 - # autosummary is empty.
2626 - return '';
2627 - }
2628 -
2629 - /**
2630 - * Add the primary page-view wikitext to the output buffer
2631 - * Saves the text into the parser cache if possible.
2632 - * Updates templatelinks if it is out of date.
2633 - *
2634 - * @param $text String
2635 - * @param $cache Boolean
2636 - * @param $parserOptions mixed ParserOptions object, or boolean false
2637 - */
2638 - public function outputWikiText( $text, $cache = true, $parserOptions = false ) {
2639 - global $wgOut;
2640 -
2641 - $this->mParserOutput = $this->getOutputFromWikitext( $text, $cache, $parserOptions );
2642 - $wgOut->addParserOutput( $this->mParserOutput );
2643 - }
2644 -
2645 - /**
26461898 * This does all the heavy lifting for outputWikitext, except it returns the parser
26471899 * output instead of sending it straight to $wgOut. Makes things nice and simple for,
26481900 * say, embedding thread pages within a discussion system (LiquidThreads)
Index: branches/iwtransclusion/phase3v3/includes/parser/Parser.php
@@ -3051,7 +3051,7 @@
30523052 * @private
30533053 */
30543054 function braceSubstitution( $piece, $frame ) {
3055 - global $wgContLang, $wgNonincludableNamespaces, $wgEnableInterwikiTranscluding, $wgEnableInterwikiTemplatesTracking;
 3055+ global $wgContLang, $wgNonincludableNamespaces;
30563056 wfProfileIn( __METHOD__ );
30573057 wfProfileIn( __METHOD__.'-setup' );
30583058
@@ -3266,15 +3266,11 @@
32673267 $text = "[[:$titleText]]";
32683268 $found = true;
32693269 }
3270 - } elseif ( $wgEnableInterwikiTranscluding && $title->isTrans() ) {
 3270+ } elseif ( $title->isTrans() ) {
32713271 // TODO: Work by Peter17 in progress
32723272
32733273 $text = Interwiki::interwikiTransclude( $title );
32743274
3275 - if ( $wgEnableInterwikiTemplatesTracking ) {
3276 - $this->registerDistantTemplate( $title );
3277 - }
3278 -
32793275 if ( $text !== false ) {
32803276 # Preprocess it like a template
32813277 $text = $this->preprocessToDom( $text, self::PTD_FOR_INCLUSION );
@@ -3433,17 +3429,6 @@
34343430 * @param Title $title
34353431 * @return mixed string or false
34363432 */
3437 - function registerDistantTemplate( $title ) {
3438 - $stuff = Parser::distantTemplateCallback( $title, $this );
3439 - $text = $stuff['text'];
3440 - $finalTitle = isset( $stuff['finalTitle'] ) ? $stuff['finalTitle'] : $title;
3441 - if ( isset( $stuff['deps'] ) ) {
3442 - foreach ( $stuff['deps'] as $dep ) {
3443 - $this->mOutput->addDistantTemplate( $dep['title'], $dep['page_id'], $dep['rev_id'] );
3444 - }
3445 - }
3446 - }
3447 -
34483433 function fetchTemplate( $title ) {
34493434 $rv = $this->fetchTemplateAndTitle( $title );
34503435 return $rv[0];
Index: branches/iwtransclusion/phase3v3/includes/parser/ParserOutput.php
@@ -306,31 +306,6 @@
307307 $this->mTemplateIds[$ns][$dbk] = $rev_id; // For versioning
308308 }
309309
310 - function addDistantTemplate( $title, $page_id, $rev_id ) {
311 - $prefix = $title->getInterwiki();
312 - if ( $prefix !=='' ) {
313 - $ns = $title->getNamespace();
314 - $dbk = $title->getDBkey();
315 -
316 - if ( !isset( $this->mDistantTemplates[$prefix] ) ) {
317 - $this->mDistantTemplates[$prefix] = array();
318 - }
319 - if ( !isset( $this->mDistantTemplates[$prefix][$ns] ) ) {
320 - $this->mDistantTemplates[$prefix][$ns] = array();
321 - }
322 - $this->mDistantTemplates[$prefix][$ns][$dbk] = $page_id;
323 -
324 - // For versioning
325 - if ( !isset( $this->mDistantTemplateIds[$prefix] ) ) {
326 - $this->mDistantTemplateIds[$prefix] = array();
327 - }
328 - if ( !isset( $this->mDistantTemplateIds[$prefix][$ns] ) ) {
329 - $this->mDistantTemplateIds[$prefix][$ns] = array();
330 - }
331 - $this->mDistantTemplateIds[$prefix][$ns][$dbk] = $rev_id;
332 - }
333 - }
334 -
335310 /**
336311 * @param $title Title object, must be an interwiki link
337312 * @throws MWException if given invalid input
Index: branches/iwtransclusion/phase3v3/includes/Linker.php
@@ -1646,48 +1646,6 @@
16471647 }
16481648
16491649 /**
1650 - * Returns HTML for the "templates used on this page" list.
1651 - *
1652 - * @param $templates Array of templates from Article::getUsedTemplate
1653 - * or similar
1654 - * @param $preview Boolean: whether this is for a preview
1655 - * @param $section Boolean: whether this is for a section edit
1656 - * @return String: HTML output
1657 - */
1658 - public function formatDistantTemplates( $templates, $preview = false, $section = false ) {
1659 - wfProfileIn( __METHOD__ );
1660 -
1661 - $outText = '';
1662 - if ( count( $templates ) > 0 ) {
1663 - # Do a batch existence check
1664 - $batch = new LinkBatch;
1665 - foreach( $templates as $title ) {
1666 - $batch->addObj( $title );
1667 - }
1668 - $batch->execute();
1669 -
1670 - # Construct the HTML
1671 - $outText = '<div class="mw-templatesUsedExplanation">';
1672 - if ( $preview ) {
1673 - $outText .= wfMsgExt( 'distanttemplatesusedpreview', array( 'parse' ), count( $templates ) );
1674 - } elseif ( $section ) {
1675 - $outText .= wfMsgExt( 'distanttemplatesusedsection', array( 'parse' ), count( $templates ) );
1676 - } else {
1677 - $outText .= wfMsgExt( 'distanttemplatesused', array( 'parse' ), count( $templates ) );
1678 - }
1679 - $outText .= "</div><ul>\n";
1680 -
1681 - usort( $templates, array( 'Title', 'compare' ) );
1682 - foreach ( $templates as $titleObj ) {
1683 - $outText .= '<li>' . $this->link( $titleObj ) . '</li>';
1684 - }
1685 - $outText .= '</ul>';
1686 - }
1687 - wfProfileOut( __METHOD__ );
1688 - return $outText;
1689 - }
1690 -
1691 - /**
16921650 * Returns HTML for the "hidden categories on this page" list.
16931651 *
16941652 * @param $hiddencats Array of hidden categories from Article::getHiddenCategories
Index: branches/iwtransclusion/phase3v3/includes/db/Database.php
@@ -1777,31 +1777,6 @@
17781778 return false;
17791779 }
17801780 }
1781 -
1782 - /**
1783 - * Build a partial where clause from a 3-d array
1784 - * The keys on each level may be either integers or strings.
1785 - *
1786 - * @param $data Array: organized as 3-d array(baseKeyVal => array(middleKeyVal => array(subKeyVal => <ignored>, ...), ...), ...)
1787 - * @param $baseKey String: field name to match the base-level keys to (eg 'gtl_to_prefix')
1788 - * @param $middleKey String: field name to match the middle-level keys to (eg 'gtl_to_namespace')
1789 - * @param $subKey String: field name to match the sub-level keys to (eg 'gtl_to_title')
1790 - * @return Mixed: string SQL fragment, or false if no items in array.
1791 - */
1792 - function makeWhereFrom3d( $data, $baseKey, $middleKey, $subKey ) {
1793 - $conds = array();
1794 - foreach ( $data as $base => $subdata ) {
1795 - foreach ( $subdata as $middle => $sub ) {
1796 - if ( count( $sub ) ) {
1797 - $conds[] = $this->makeList(
1798 - array( $baseKey => $base,
1799 - $middleKey => $middle,
1800 - $subKey => array_keys( $sub ) ),
1801 - LIST_AND
1802 - );
1803 - }
1804 - }
1805 - }
18061781
18071782 /**
18081783 * Bitwise operations
Property changes on: branches/iwtransclusion/phase3v3/includes/db/Database.php
___________________________________________________________________
Modified: svn:mergeinfo
18091784 Reverse-merged /branches/iwtransclusion/phase3/includes/db/Database.php:r70764
18101785 Reverse-merged /branches/iwtransclusion/phase3v2/includes/db/Database.php:r87108
Index: branches/iwtransclusion/phase3v3/includes/EditPage.php
@@ -1319,8 +1319,8 @@
13201320 * @param $formCallback Callback that takes an OutputPage parameter; will be called
13211321 * during form output near the top, for captchas and the like.
13221322 */
1323 - function showEditForm( $formCallback=null ) {
1324 - global $wgOut, $wgUser, $wgTitle, $wgEnableInterwikiTranscluding, $wgEnableInterwikiTemplatesTracking;
 1323+ function showEditForm( $formCallback = null ) {
 1324+ global $wgOut, $wgUser;
13251325
13261326 wfProfileIn( __METHOD__ );
13271327
@@ -1365,9 +1365,6 @@
13661366
13671367 $templates = $this->getTemplates();
13681368 $formattedtemplates = Linker::formatTemplates( $templates, $this->preview, $this->section != '');
1369 -
1370 - $distantTemplates = $this->getDistantTemplates();
1371 - $formattedDistantTemplates = $sk->formatDistantTemplates( $distantTemplates, $this->preview, $this->section != '' );
13721369
13731370 $hiddencats = $this->mArticle->getHiddenCategories();
13741371 $formattedhiddencats = Linker::formatHiddenCategories( $hiddencats );
@@ -1467,21 +1464,6 @@
14681465 <div class='templatesUsed'>
14691466 {$formattedtemplates}
14701467 </div>
1471 -HTML
1472 -);
1473 -
1474 - if ( $wgEnableInterwikiTranscluding && $wgEnableInterwikiTemplatesTracking ) {
1475 - $wgOut->addHTML( <<<HTML
1476 -{$this->editFormTextAfterTools}
1477 -<div class='distantTemplatesUsed'>
1478 -{$formattedDistantTemplates}
1479 -</div>
1480 -HTML
1481 -);
1482 - }
1483 -
1484 - $wgOut->addHTML( <<<HTML
1485 -{$this->editFormTextAfterTools}
14861468 <div class='hiddencats'>
14871469 {$formattedhiddencats}
14881470 </div>
@@ -2137,28 +2119,6 @@
21382120 return $this->mArticle->getUsedTemplates();
21392121 }
21402122 }
2141 -
2142 - function getDistantTemplates() {
2143 - global $wgEnableInterwikiTemplatesTracking;
2144 - if ( !$wgEnableInterwikiTemplatesTracking ) {
2145 - return array( );
2146 - }
2147 - if ( $this->preview || $this->section != '' ) {
2148 - $templates = array();
2149 - if ( !isset( $this->mParserOutput ) ) return $templates;
2150 - $templatesList = $this->mParserOutput->getDistantTemplates();
2151 - foreach( $templatesList as $prefix => $templatesbyns ) {
2152 - foreach( $templatesbyns as $ns => $template ) {
2153 - foreach( array_keys( $template ) as $dbk ) {
2154 - $templates[] = Title::makeTitle( $ns, $dbk, null, $prefix );
2155 - }
2156 - }
2157 - }
2158 - return $templates;
2159 - } else {
2160 - return $this->mArticle->getUsedDistantTemplates();
2161 - }
2162 - }
21632123
21642124 /**
21652125 * Call the stock "user is blocked" page
Index: branches/iwtransclusion/phase3v3/includes/OutputPage.php
@@ -2095,9 +2095,6 @@
20962096 * @param $action String: action that was denied or null if unknown
20972097 */
20982098 public function readOnlyPage( $source = null, $protected = false, $reasons = array(), $action = null ) {
2099 - global $wgUser, $wgEnableInterwikiTranscluding, $wgEnableInterwikiTemplatesTracking;
2100 - $skin = $wgUser->getSkin();
2101 -
21022099 $this->setRobotPolicy( 'noindex,nofollow' );
21032100 $this->setArticleRelated( false );
21042101
@@ -2143,12 +2140,6 @@
21442141 $templates
21452142 </div>
21462143 " );
2147 - if ( $wgEnableInterwikiTranscluding && $wgEnableInterwikiTemplatesTracking ) {
2148 - $this->addHTML( "<div class='distantTemplatesUsed'>
2149 -{$skin->formatDistantTemplates( $article->getUsedDistantTemplates( ) )}
2150 -</div>
2151 -" );
2152 - }
21532144 }
21542145
21552146 # If the title doesn't exist, it's fairly pointless to print a return
Property changes on: branches/iwtransclusion/phase3v3/includes/OutputPage.php
___________________________________________________________________
Modified: svn:mergeinfo
21562147 Reverse-merged /branches/iwtransclusion/phase3/includes/OutputPage.php:r70764
21572148 Reverse-merged /branches/iwtransclusion/phase3v2/includes/OutputPage.php:r87108
Index: branches/iwtransclusion/phase3v3/includes/Title.php
@@ -21,7 +21,6 @@
2222 */
2323
2424 /**
25 -
2625 * Represents a title within MediaWiki.
2726 * Optionally may contain an interwiki designation or namespace.
2827 * @note This class can fetch various kinds of data from the database;
@@ -42,7 +41,13 @@
4342 */
4443 const CACHE_MAX = 1000;
4544
 45+ /**
 46+ * Used to be GAID_FOR_UPDATE define. Used with getArticleID() and friends
 47+ * to use the master DB
 48+ */
 49+ const GAID_FOR_UPDATE = 1;
4650
 51+
4752 /**
4853 * @name Private member variables
4954 * Please use the accessor functions instead.
@@ -68,11 +73,11 @@
6974 var $mCascadeSources; ///< Where are the cascading restrictions coming from on this page?
7075 var $mRestrictionsLoaded = false; ///< Boolean for initialisation on demand
7176 var $mPrefixedText; ///< Text form including namespace/interwiki, initialised on demand
72 - var $mTitleProtection; ///< Cached value of getTitleProtection
 77+ var $mTitleProtection; ///< Cached value for getTitleProtection (create protection)
7378 # Don't change the following default, NS_MAIN is hardcoded in several
7479 # places. See bug 696.
7580 var $mDefaultNamespace = NS_MAIN; // /< Namespace index when there is no namespace
76 - # Zero except in {{transclusion}} tags
 81+ # Zero except in {{transclusion}} tags
7782 var $mWatched = null; // /< Is $wgUser watching this page? null if unfilled, accessed through userIsWatching()
7883 var $mLength = -1; // /< The page length, 0 for special pages
7984 var $mRedirect = null; // /< Is the article at this title a redirect?
@@ -83,17 +88,16 @@
8489
8590 /**
8691 * Constructor
87 - * @private
8892 */
89 - /* private */ function __construct() { }
 93+ /*protected*/ function __construct() { }
9094
9195 /**
9296 * Create a new Title from a prefixed DB key
9397 *
94 - * @param $key \type{\string} The database key, which has underscores
 98+ * @param $key String the database key, which has underscores
9599 * instead of spaces, possibly including namespace and
96100 * interwiki prefixes
97 - * @return \type{Title} the new object, or NULL on an error
 101+ * @return Title, or NULL on an error
98102 */
99103 public static function newFromDBkey( $key ) {
100104 $t = new Title();
@@ -109,13 +113,13 @@
110114 * Create a new Title from text, such as what one would find in a link. De-
111115 * codes any HTML entities in the text.
112116 *
113 - * @param $text string The link text; spaces, prefixes, and an
 117+ * @param $text String the link text; spaces, prefixes, and an
114118 * initial ':' indicating the main namespace are accepted.
115 - * @param $defaultNamespace int The namespace to use if none is speci-
 119+ * @param $defaultNamespace Int the namespace to use if none is speci-
116120 * fied by a prefix. If you want to force a specific namespace even if
117121 * $text might begin with a namespace prefix, use makeTitle() or
118122 * makeTitleSafe().
119 - * @return Title The new object, or null on an error.
 123+ * @return Title, or null on an error.
120124 */
121125 public static function newFromText( $text, $defaultNamespace = NS_MAIN ) {
122126 if ( is_object( $text ) ) {
@@ -134,9 +138,7 @@
135139 return Title::$titleCache[$text];
136140 }
137141
138 - /**
139 - * Convert things like &eacute; &#257; or &#x3017; into normalized(bug 14952) text
140 - */
 142+ # Convert things like &eacute; &#257; or &#x3017; into normalized (bug 14952) text
141143 $filteredText = Sanitizer::decodeCharReferencesAndNormalize( $text );
142144
143145 $t = new Title();
@@ -173,8 +175,8 @@
174176 * Create a new Title from URL-encoded text. Ensures that
175177 * the given title's length does not exceed the maximum.
176178 *
177 - * @param $url \type{\string} the title, as might be taken from a URL
178 - * @return \type{Title} the new object, or NULL on an error
 179+ * @param $url String the title, as might be taken from a URL
 180+ * @return Title the new object, or NULL on an error
179181 */
180182 public static function newFromURL( $url ) {
181183 global $wgLegalTitleChars;
@@ -198,12 +200,12 @@
199201 /**
200202 * Create a new Title from an article ID
201203 *
202 - * @param $id \type{\int} the page_id corresponding to the Title to create
203 - * @param $flags \type{\int} use GAID_FOR_UPDATE to use master
204 - * @return \type{Title} the new object, or NULL on an error
 204+ * @param $id Int the page_id corresponding to the Title to create
 205+ * @param $flags Int use Title::GAID_FOR_UPDATE to use master
 206+ * @return Title the new object, or NULL on an error
205207 */
206208 public static function newFromID( $id, $flags = 0 ) {
207 - $db = ( $flags & GAID_FOR_UPDATE ) ? wfGetDB( DB_MASTER ) : wfGetDB( DB_SLAVE );
 209+ $db = ( $flags & self::GAID_FOR_UPDATE ) ? wfGetDB( DB_MASTER ) : wfGetDB( DB_SLAVE );
208210 $row = $db->selectRow( 'page', '*', array( 'page_id' => $id ), __METHOD__ );
209211 if ( $row !== false ) {
210212 $title = Title::newFromRow( $row );
@@ -216,15 +218,15 @@
217219 /**
218220 * Make an array of titles from an array of IDs
219221 *
220 - * @param $ids \type{\arrayof{\int}} Array of IDs
221 - * @return \type{\arrayof{Title}} Array of Titles
 222+ * @param $ids Array of Int Array of IDs
 223+ * @return Array of Titles
222224 */
223225 public static function newFromIDs( $ids ) {
224226 if ( !count( $ids ) ) {
225227 return array();
226228 }
227229 $dbr = wfGetDB( DB_SLAVE );
228 -
 230+
229231 $res = $dbr->select(
230232 'page',
231233 array(
@@ -245,8 +247,8 @@
246248 /**
247249 * Make a Title object from a DB row
248250 *
249 - * @param $row \type{Row} (needs at least page_title,page_namespace)
250 - * @return \type{Title} corresponding Title
 251+ * @param $row Object database row (needs at least page_title,page_namespace)
 252+ * @return Title corresponding Title
251253 */
252254 public static function newFromRow( $row ) {
253255 $t = self::makeTitle( $row->page_namespace, $row->page_title );
@@ -286,11 +288,11 @@
287289 * For convenience, spaces are converted to underscores so that
288290 * eg user_text fields can be used directly.
289291 *
290 - * @param $ns \type{\int} the namespace of the article
291 - * @param $title \type{\string} the unprefixed database key form
292 - * @param $fragment \type{\string} The link fragment (after the "#")
293 - * @param $interwiki \type{\string} The interwiki prefix
294 - * @return \type{Title} the new object
 292+ * @param $ns Int the namespace of the article
 293+ * @param $title String the unprefixed database key form
 294+ * @param $fragment String the link fragment (after the "#")
 295+ * @param $interwiki String the interwiki prefix
 296+ * @return Title the new object
295297 */
296298 public static function &makeTitle( $ns, $title, $fragment = '', $interwiki = '' ) {
297299 $t = new Title();
@@ -309,11 +311,11 @@
310312 * The parameters will be checked for validity, which is a bit slower
311313 * than makeTitle() but safer for user-provided data.
312314 *
313 - * @param $ns \type{\int} the namespace of the article
314 - * @param $title \type{\string} the database key form
315 - * @param $fragment \type{\string} The link fragment (after the "#")
316 - * @param $interwiki \type{\string} The interwiki prefix
317 - * @return \type{Title} the new object, or NULL on an error
 315+ * @param $ns Int the namespace of the article
 316+ * @param $title String database key form
 317+ * @param $fragment String the link fragment (after the "#")
 318+ * @param $interwiki String interwiki prefix
 319+ * @return Title the new object, or NULL on an error
318320 */
319321 public static function makeTitleSafe( $ns, $title, $fragment = '', $interwiki = '' ) {
320322 $t = new Title();
@@ -328,7 +330,7 @@
329331 /**
330332 * Create a new Title for the Main Page
331333 *
332 - * @return \type{Title} the new object
 334+ * @return Title the new object
333335 */
334336 public static function newMainPage() {
335337 $title = Title::newFromText( wfMsgForContent( 'mainpage' ) );
@@ -345,8 +347,8 @@
346348 * This will only return the very next target, useful for
347349 * the redirect table and other checks that don't need full recursion
348350 *
349 - * @param $text \type{\string} Text with possible redirect
350 - * @return \type{Title} The corresponding Title
 351+ * @param $text String: Text with possible redirect
 352+ * @return Title: The corresponding Title
351353 */
352354 public static function newFromRedirect( $text ) {
353355 return self::newFromRedirectInternal( $text );
@@ -358,8 +360,8 @@
359361 * This will recurse down $wgMaxRedirects times or until a non-redirect target is hit
360362 * in order to provide (hopefully) the Title of the final destination instead of another redirect
361363 *
362 - * @param $text \type{\string} Text with possible redirect
363 - * @return \type{Title} The corresponding Title
 364+ * @param $text String Text with possible redirect
 365+ * @return Title
364366 */
365367 public static function newFromRedirectRecurse( $text ) {
366368 $titles = self::newFromRedirectArray( $text );
@@ -372,15 +374,11 @@
373375 * The last element in the array is the final destination after all redirects
374376 * have been resolved (up to $wgMaxRedirects times)
375377 *
376 - * @param $text \type{\string} Text with possible redirect
377 - * @return \type{\array} Array of Titles, with the destination last
 378+ * @param $text String Text with possible redirect
 379+ * @return Array of Titles, with the destination last
378380 */
379381 public static function newFromRedirectArray( $text ) {
380382 global $wgMaxRedirects;
381 - // are redirects disabled?
382 - if ( $wgMaxRedirects < 1 ) {
383 - return null;
384 - }
385383 $title = self::newFromRedirectInternal( $text );
386384 if ( is_null( $title ) ) {
387385 return null;
@@ -411,10 +409,15 @@
412410 * Really extract the redirect destination
413411 * Do not call this function directly, use one of the newFromRedirect* functions above
414412 *
415 - * @param $text \type{\string} Text with possible redirect
416 - * @return \type{Title} The corresponding Title
 413+ * @param $text String Text with possible redirect
 414+ * @return Title
417415 */
418416 protected static function newFromRedirectInternal( $text ) {
 417+ global $wgMaxRedirects;
 418+ if ( $wgMaxRedirects < 1 ) {
 419+ //redirects are disabled, so quit early
 420+ return null;
 421+ }
419422 $redir = MagicWord::get( 'redirect' );
420423 $text = trim( $text );
421424 if ( $redir->matchStartAndRemove( $text ) ) {
@@ -427,9 +430,7 @@
428431 // and URL-decode links
429432 if ( strpos( $m[1], '%' ) !== false ) {
430433 // Match behavior of inline link parsing here;
431 - // don't interpret + as " " most of the time!
432 - // It might be safe to just use rawurldecode instead, though.
433 - $m[1] = urldecode( ltrim( $m[1], ':' ) );
 434+ $m[1] = rawurldecode( ltrim( $m[1], ':' ) );
434435 }
435436 $title = Title::newFromText( $m[1] );
436437 // If the title is a redirect to bad special pages or is invalid, return null
@@ -449,9 +450,8 @@
450451 /**
451452 * Get the prefixed DB key associated with an ID
452453 *
453 - * @param $id \type{\int} the page_id of the article
454 - * @return \type{Title} an object representing the article, or NULL
455 - * if no such article was found
 454+ * @param $id Int the page_id of the article
 455+ * @return Title an object representing the article, or NULL if no such article was found
456456 */
457457 public static function nameOf( $id ) {
458458 $dbr = wfGetDB( DB_SLAVE );
@@ -473,7 +473,7 @@
474474 /**
475475 * Get a regex character class describing the legal characters in a link
476476 *
477 - * @return \type{\string} the list of characters, not delimited
 477+ * @return String the list of characters, not delimited
478478 */
479479 public static function legalChars() {
480480 global $wgLegalTitleChars;
@@ -484,10 +484,9 @@
485485 * Get a string representation of a title suitable for
486486 * including in a search index
487487 *
488 - * @param $ns \type{\int} a namespace index
489 - * @param $title \type{\string} text-form main part
490 - * @return \type{\string} a stripped-down title string ready for the
491 - * search index
 488+ * @param $ns Int a namespace index
 489+ * @param $title String text-form main part
 490+ * @return String a stripped-down title string ready for the search index
492491 */
493492 public static function indexTitle( $ns, $title ) {
494493 global $wgContLang;
@@ -512,11 +511,11 @@
513512 /**
514513 * Make a prefixed DB key from a DB key and a namespace index
515514 *
516 - * @param $ns \type{\int} numerical representation of the namespace
517 - * @param $title \type{\string} the DB key form the title
518 - * @param $fragment \type{\string} The link fragment (after the "#")
519 - * @param $interwiki \type{\string} The interwiki prefix
520 - * @return \type{\string} the prefixed form of the title
 515+ * @param $ns Int numerical representation of the namespace
 516+ * @param $title String the DB key form the title
 517+ * @param $fragment String The link fragment (after the "#")
 518+ * @param $interwiki String The interwiki prefix
 519+ * @return String the prefixed form of the title
521520 */
522521 public static function makeName( $ns, $title, $fragment = '', $interwiki = '' ) {
523522 global $wgContLang;
@@ -536,8 +535,7 @@
537536 * Determine whether the object refers to a page within
538537 * this project.
539538 *
540 - * @return \type{\bool} TRUE if this is an in-project interwiki link
541 - * or a wikilink, FALSE otherwise
 539+ * @return Bool TRUE if this is an in-project interwiki link or a wikilink, FALSE otherwise
542540 */
543541 public function isLocal() {
544542 if ( $this->mInterwiki != '' ) {
@@ -551,7 +549,7 @@
552550 * Determine whether the object refers to a page within
553551 * this project and is transcludable.
554552 *
555 - * @return \type{\bool} TRUE if this is transcludable
 553+ * @return Bool TRUE if this is transcludable
556554 */
557555 public function isTrans() {
558556 if ( $this->mInterwiki == '' ) {
@@ -560,25 +558,11 @@
561559
562560 return Interwiki::fetch( $this->mInterwiki )->isTranscludable();
563561 }
564 -
565 - /**
566 - * Returns the API URL of the distant wiki
567 - * which owns the object.
568 - *
569 - * @return \type{\string} the API URL
570 - */
571 - public function getTransAPI() {
572 - if ( $this->mInterwiki == '' )
573 - return false;
574562
575 - return Interwiki::fetch( $this->mInterwiki )->getAPI();
576 - }
577 -
578563 /**
579 - * Returns the DB name of the distant wiki
580 - * which owns the object.
 564+ * Returns the DB name of the distant wiki which owns the object.
581565 *
582 - * @return \type{\string} the DB name
 566+ * @return String the DB name
583567 */
584568 public function getTransWikiID() {
585569 if ( $this->mInterwiki == '' ) {
@@ -610,35 +594,35 @@
611595 /**
612596 * Get the text form (spaces not underscores) of the main part
613597 *
614 - * @return \type{\string} Main part of the title
 598+ * @return String Main part of the title
615599 */
616600 public function getText() { return $this->mTextform; }
617601
618602 /**
619603 * Get the URL-encoded form of the main part
620604 *
621 - * @return \type{\string} Main part of the title, URL-encoded
 605+ * @return String Main part of the title, URL-encoded
622606 */
623607 public function getPartialURL() { return $this->mUrlform; }
624608
625609 /**
626610 * Get the main part with underscores
627611 *
628 - * @return \type{\string} Main part of the title, with underscores
 612+ * @return String: Main part of the title, with underscores
629613 */
630614 public function getDBkey() { return $this->mDbkeyform; }
631615
632616 /**
633 - * Get the namespace index, i.e.\ one of the NS_xxxx constants.
 617+ * Get the namespace index, i.e. one of the NS_xxxx constants.
634618 *
635 - * @return \type{\int} Namespace index
 619+ * @return Integer: Namespace index
636620 */
637621 public function getNamespace() { return $this->mNamespace; }
638622
639623 /**
640624 * Get the namespace text
641625 *
642 - * @return \type{\string} Namespace text
 626+ * @return String: Namespace text
643627 */
644628 public function getNsText() {
645629 global $wgContLang;
@@ -654,13 +638,20 @@
655639 return MWNamespace::getCanonicalName( $this->mNamespace );
656640 }
657641 }
 642+
 643+ if ( $wgContLang->needsGenderDistinction() &&
 644+ MWNamespace::hasGenderDistinction( $this->mNamespace ) ) {
 645+ $gender = GenderCache::singleton()->getGenderOf( $this->getText(), __METHOD__ );
 646+ return $wgContLang->getGenderNsText( $this->mNamespace, $gender );
 647+ }
 648+
658649 return $wgContLang->getNsText( $this->mNamespace );
659650 }
660651
661652 /**
662653 * Get the DB key with the initial letter case as specified by the user
663654 *
664 - * @return \type{\string} DB key
 655+ * @return String DB key
665656 */
666657 function getUserCaseDBKey() {
667658 return $this->mUserCaseDBKey;
@@ -669,7 +660,7 @@
670661 /**
671662 * Get the namespace text of the subject (rather than talk) page
672663 *
673 - * @return \type{\string} Namespace text
 664+ * @return String Namespace text
674665 */
675666 public function getSubjectNsText() {
676667 global $wgContLang;
@@ -679,7 +670,7 @@
680671 /**
681672 * Get the namespace text of the talk page
682673 *
683 - * @return \type{\string} Namespace text
 674+ * @return String Namespace text
684675 */
685676 public function getTalkNsText() {
686677 global $wgContLang;
@@ -689,7 +680,7 @@
690681 /**
691682 * Could this title have a corresponding talk page?
692683 *
693 - * @return \type{\bool} TRUE or FALSE
 684+ * @return Bool TRUE or FALSE
694685 */
695686 public function canTalk() {
696687 return( MWNamespace::canTalk( $this->mNamespace ) );
@@ -698,20 +689,20 @@
699690 /**
700691 * Get the interwiki prefix (or null string)
701692 *
702 - * @return \type{\string} Interwiki prefix
 693+ * @return String Interwiki prefix
703694 */
704695 public function getInterwiki() { return $this->mInterwiki; }
705696
706697 /**
707698 * Get the Title fragment (i.e.\ the bit after the #) in text form
708699 *
709 - * @return \type{\string} Title fragment
 700+ * @return String Title fragment
710701 */
711702 public function getFragment() { return $this->mFragment; }
712703
713704 /**
714705 * Get the fragment in URL form, including the "#" character if there is one
715 - * @return \type{\string} Fragment in URL form
 706+ * @return String Fragment in URL form
716707 */
717708 public function getFragmentForURL() {
718709 if ( $this->mFragment == '' ) {
@@ -724,14 +715,14 @@
725716 /**
726717 * Get the default namespace index, for when there is no namespace
727718 *
728 - * @return \type{\int} Default namespace index
 719+ * @return Int Default namespace index
729720 */
730721 public function getDefaultNamespace() { return $this->mDefaultNamespace; }
731722
732723 /**
733724 * Get title for search index
734725 *
735 - * @return \type{\string} a stripped-down title string ready for the
 726+ * @return String a stripped-down title string ready for the
736727 * search index
737728 */
738729 public function getIndexTitle() {
@@ -741,7 +732,7 @@
742733 /**
743734 * Get the prefixed database key form
744735 *
745 - * @return \type{\string} the prefixed title, with underscores and
 736+ * @return String the prefixed title, with underscores and
746737 * any interwiki and namespace prefixes
747738 */
748739 public function getPrefixedDBkey() {
@@ -754,7 +745,7 @@
755746 * Get the prefixed title with spaces.
756747 * This is the form usually used for display
757748 *
758 - * @return \type{\string} the prefixed title, with spaces
 749+ * @return String the prefixed title, with spaces
759750 */
760751 public function getPrefixedText() {
761752 // @todo FIXME: Bad usage of empty() ?
@@ -784,8 +775,7 @@
785776 * Get the prefixed title with spaces, plus any fragment
786777 * (part beginning with '#')
787778 *
788 - * @return \type{\string} the prefixed title, with spaces and
789 - * the fragment, including '#'
 779+ * @return String the prefixed title, with spaces and the fragment, including '#'
790780 */
791781 public function getFullText() {
792782 $text = $this->getPrefixedText();
@@ -798,7 +788,7 @@
799789 /**
800790 * Get the base page name, i.e. the leftmost part before any slashes
801791 *
802 - * @return \type{\string} Base name
 792+ * @return String Base name
803793 */
804794 public function getBaseText() {
805795 if ( !MWNamespace::hasSubpages( $this->mNamespace ) ) {
@@ -816,7 +806,7 @@
817807 /**
818808 * Get the lowest-level subpage name, i.e. the rightmost part after any slashes
819809 *
820 - * @return \type{\string} Subpage name
 810+ * @return String Subpage name
821811 */
822812 public function getSubpageText() {
823813 if ( !MWNamespace::hasSubpages( $this->mNamespace ) ) {
@@ -829,7 +819,7 @@
830820 /**
831821 * Get a URL-encoded form of the subpage text
832822 *
833 - * @return \type{\string} URL-encoded subpage name
 823+ * @return String URL-encoded subpage name
834824 */
835825 public function getSubpageUrlForm() {
836826 $text = $this->getSubpageText();
@@ -840,7 +830,7 @@
841831 /**
842832 * Get a URL-encoded title (not an actual URL) including interwiki
843833 *
844 - * @return \type{\string} the URL-encoded form
 834+ * @return String the URL-encoded form
845835 */
846836 public function getPrefixedURL() {
847837 $s = $this->prefix( $this->mDbkeyform );
@@ -855,8 +845,8 @@
856846 * @param $query \twotypes{\string,\array} an optional query string, not used for interwiki
857847 * links. Can be specified as an associative array as well, e.g.,
858848 * array( 'action' => 'edit' ) (keys and values will be URL-escaped).
859 - * @param $variant \type{\string} language variant of url (for sr, zh..)
860 - * @return \type{\string} the URL
 849+ * @param $variant String language variant of url (for sr, zh..)
 850+ * @return String the URL
861851 */
862852 public function getFullURL( $query = '', $variant = false ) {
863853 global $wgServer, $wgRequest;
@@ -902,25 +892,17 @@
903893 * $wgArticlePath will be used. Can be specified as an associative array
904894 * as well, e.g., array( 'action' => 'edit' ) (keys and values will be
905895 * URL-escaped).
906 - * @param $variant \type{\string} language variant of url (for sr, zh..)
907 - * @return \type{\string} the URL
 896+ * @param $variant String language variant of url (for sr, zh..)
 897+ * @return String the URL
908898 */
909899 public function getLocalURL( $query = '', $variant = false ) {
910900 global $wgArticlePath, $wgScript, $wgServer, $wgRequest;
911 - global $wgVariantArticlePath, $wgContLang, $wgUser;
 901+ global $wgVariantArticlePath, $wgContLang;
912902
913903 if ( is_array( $query ) ) {
914904 $query = wfArrayToCGI( $query );
915905 }
916906
917 - // internal links should point to same variant as current page (only anonymous users)
918 - if ( !$variant && $wgContLang->hasVariants() && !$wgUser->isLoggedIn() ) {
919 - $pref = $wgContLang->getPreferredVariant( false );
920 - if ( $pref != $wgContLang->getCode() ) {
921 - $variant = $pref;
922 - }
923 - }
924 -
925907 if ( $this->isExternal() ) {
926908 $url = $this->getFullURL();
927909 if ( $query ) {
@@ -992,12 +974,12 @@
993975 * The result obviously should not be URL-escaped, but does need to be
994976 * HTML-escaped if it's being output in HTML.
995977 *
996 - * @param $query \type{\arrayof{\string}} An associative array of key => value pairs for the
 978+ * @param $query Array of Strings An associative array of key => value pairs for the
997979 * query string. Keys and values will be escaped.
998 - * @param $variant \type{\string} Language variant of URL (for sr, zh..). Ignored
 980+ * @param $variant String language variant of URL (for sr, zh..). Ignored
999981 * for external links. Default is "false" (same variant as current page,
1000982 * for anonymous users).
1001 - * @return \type{\string} the URL
 983+ * @return String the URL
1002984 */
1003985 public function getLinkUrl( $query = array(), $variant = false ) {
1004986 wfProfileIn( __METHOD__ );
@@ -1016,8 +998,8 @@
1017999 * Get an HTML-escaped version of the URL form, suitable for
10181000 * using in a link, without a server name or fragment
10191001 *
1020 - * @param $query \type{\string} an optional query string
1021 - * @return \type{\string} the URL
 1002+ * @param $query String an optional query string
 1003+ * @return String the URL
10221004 */
10231005 public function escapeLocalURL( $query = '' ) {
10241006 return htmlspecialchars( $this->getLocalURL( $query ) );
@@ -1027,8 +1009,8 @@
10281010 * Get an HTML-escaped version of the URL form, suitable for
10291011 * using in a link, including the server name and fragment
10301012 *
1031 - * @param $query \type{\string} an optional query string
1032 - * @return \type{\string} the URL
 1013+ * @param $query String an optional query string
 1014+ * @return String the URL
10331015 */
10341016 public function escapeFullURL( $query = '' ) {
10351017 return htmlspecialchars( $this->getFullURL( $query ) );
@@ -1039,13 +1021,14 @@
10401022 * - Used in various Squid-related code, in case we have a different
10411023 * internal hostname for the server from the exposed one.
10421024 *
1043 - * @param $query \type{\string} an optional query string
1044 - * @param $variant \type{\string} language variant of url (for sr, zh..)
1045 - * @return \type{\string} the URL
 1025+ * @param $query String an optional query string
 1026+ * @param $variant String language variant of url (for sr, zh..)
 1027+ * @return String the URL
10461028 */
10471029 public function getInternalURL( $query = '', $variant = false ) {
1048 - global $wgInternalServer;
1049 - $url = $wgInternalServer . $this->getLocalURL( $query, $variant );
 1030+ global $wgInternalServer, $wgServer;
 1031+ $server = $wgInternalServer !== false ? $wgInternalServer : $wgServer;
 1032+ $url = $server . $this->getLocalURL( $query, $variant );
10501033 wfRunHooks( 'GetInternalURL', array( &$this, &$url, $query ) );
10511034 return $url;
10521035 }
@@ -1053,7 +1036,7 @@
10541037 /**
10551038 * Get the edit URL for this Title
10561039 *
1057 - * @return \type{\string} the URL, or a null string if this is an
 1040+ * @return String the URL, or a null string if this is an
10581041 * interwiki link
10591042 */
10601043 public function getEditURL() {
@@ -1069,7 +1052,7 @@
10701053 * Get the HTML-escaped displayable text form.
10711054 * Used for the title field in <a> tags.
10721055 *
1073 - * @return \type{\string} the text, including any prefixes
 1056+ * @return String the text, including any prefixes
10741057 */
10751058 public function getEscapedText() {
10761059 return htmlspecialchars( $this->getPrefixedText() );
@@ -1078,7 +1061,7 @@
10791062 /**
10801063 * Is this Title interwiki?
10811064 *
1082 - * @return \type{\bool}
 1065+ * @return Bool
10831066 */
10841067 public function isExternal() {
10851068 return ( $this->mInterwiki != '' );
@@ -1087,8 +1070,8 @@
10881071 /**
10891072 * Is this page "semi-protected" - the *only* protection is autoconfirm?
10901073 *
1091 - * @param $action \type{\string} Action to check (default: edit)
1092 - * @return \type{\bool}
 1074+ * @param $action String Action to check (default: edit)
 1075+ * @return Bool
10931076 */
10941077 public function isSemiProtected( $action = 'edit' ) {
10951078 if ( $this->exists() ) {
@@ -1113,9 +1096,9 @@
11141097 /**
11151098 * Does the title correspond to a protected article?
11161099 *
1117 - * @param $action \type{\string} the action the page is protected from,
 1100+ * @param $action String the action the page is protected from,
11181101 * by default checks all actions.
1119 - * @return \type{\bool}
 1102+ * @return Bool
11201103 */
11211104 public function isProtected( $action = '' ) {
11221105 global $wgRestrictionLevels;
@@ -1145,7 +1128,7 @@
11461129 /**
11471130 * Is this a conversion table for the LanguageConverter?
11481131 *
1149 - * @return \type{\bool}
 1132+ * @return Bool
11501133 */
11511134 public function isConversionTable() {
11521135 if(
@@ -1162,7 +1145,7 @@
11631146 /**
11641147 * Is $wgUser watching this page?
11651148 *
1166 - * @return \type{\bool}
 1149+ * @return Bool
11671150 */
11681151 public function userIsWatching() {
11691152 global $wgUser;
@@ -1187,25 +1170,26 @@
11881171 *
11891172 * May provide false positives, but should never provide a false negative.
11901173 *
1191 - * @param $action \type{\string} action that permission needs to be checked for
1192 - * @return \type{\bool}
 1174+ * @param $action String action that permission needs to be checked for
 1175+ * @return Bool
11931176 */
11941177 public function quickUserCan( $action ) {
11951178 return $this->userCan( $action, false );
11961179 }
11971180
11981181 /**
1199 - * Determines if $wgUser is unable to edit this page because it has been protected
 1182+ * Determines if $user is unable to edit this page because it has been protected
12001183 * by $wgNamespaceProtection.
12011184 *
12021185 * @param $user User object to check permissions
12031186 * @return Bool
12041187 */
1205 - public function isNamespaceProtected() {
1206 - global $wgNamespaceProtection, $wgUser;
 1188+ public function isNamespaceProtected( User $user ) {
 1189+ global $wgNamespaceProtection;
 1190+
12071191 if ( isset( $wgNamespaceProtection[$this->mNamespace] ) ) {
12081192 foreach ( (array)$wgNamespaceProtection[$this->mNamespace] as $right ) {
1209 - if ( $right != '' && !$wgUser->isAllowed( $right ) ) {
 1193+ if ( $right != '' && !$user->isAllowed( $right ) ) {
12101194 return true;
12111195 }
12121196 }
@@ -1216,9 +1200,9 @@
12171201 /**
12181202 * Can $wgUser perform $action on this page?
12191203 *
1220 - * @param $action \type{\string} action that permission needs to be checked for
1221 - * @param $doExpensiveQueries \type{\bool} Set this to false to avoid doing unnecessary queries.
1222 - * @return \type{\bool}
 1204+ * @param $action String action that permission needs to be checked for
 1205+ * @param $doExpensiveQueries Bool Set this to false to avoid doing unnecessary queries.
 1206+ * @return Bool
12231207 */
12241208 public function userCan( $action, $doExpensiveQueries = true ) {
12251209 global $wgUser;
@@ -1238,14 +1222,6 @@
12391223 * @return Array of arguments to wfMsg to explain permissions problems.
12401224 */
12411225 public function getUserPermissionsErrors( $action, $user, $doExpensiveQueries = true, $ignoreErrors = array() ) {
1242 - if ( !StubObject::isRealObject( $user ) ) {
1243 - // Since StubObject is always used on globals, we can
1244 - // unstub $wgUser here and set $user = $wgUser
1245 - global $wgUser;
1246 - $wgUser->_unstub( '', 5 );
1247 - $user = $wgUser;
1248 - }
1249 -
12501226 $errors = $this->getUserPermissionsErrorsInternal( $action, $user, $doExpensiveQueries );
12511227
12521228 // Remove the errors being ignored.
@@ -1316,8 +1292,6 @@
13171293 $errors[] = array( 'cant-move-to-user-page' );
13181294 }
13191295 } elseif ( !$user->isAllowed( $action, $ns ) ) {
1320 - $return = null;
1321 -
13221296 // We avoid expensive display logic for quickUserCan's and such
13231297 $groups = false;
13241298 if ( !$short ) {
@@ -1368,10 +1342,18 @@
13691343
13701344 /**
13711345 * Check various permission hooks
1372 - * @see checkQuickPermissions for parameter information
 1346+ *
 1347+ * @param $action String the action to check
 1348+ * @param $user User user to check
 1349+ * @param $errors Array list of current errors
 1350+ * @param $doExpensiveQueries Boolean whether or not to perform expensive queries
 1351+ * @param $short Boolean short circuit on first error
 1352+ *
 1353+ * @return Array list of errors
13731354 */
13741355 private function checkPermissionHooks( $action, $user, $errors, $doExpensiveQueries, $short ) {
13751356 // Use getUserPermissionsErrors instead
 1357+ $result = '';
13761358 if ( !wfRunHooks( 'userCan', array( &$this, &$user, $action, &$result ) ) ) {
13771359 return $result ? array() : array( array( 'badaccess-group0' ) );
13781360 }
@@ -1390,7 +1372,14 @@
13911373
13921374 /**
13931375 * Check permissions on special pages & namespaces
1394 - * @see checkQuickPermissions for parameter information
 1376+ *
 1377+ * @param $action String the action to check
 1378+ * @param $user User user to check
 1379+ * @param $errors Array list of current errors
 1380+ * @param $doExpensiveQueries Boolean whether or not to perform expensive queries
 1381+ * @param $short Boolean short circuit on first error
 1382+ *
 1383+ * @return Array list of errors
13951384 */
13961385 private function checkSpecialsAndNSPermissions( $action, $user, $errors, $doExpensiveQueries, $short ) {
13971386 # Only 'createaccount' and 'execute' can be performed on
@@ -1401,7 +1390,7 @@
14021391 }
14031392
14041393 # Check $wgNamespaceProtection for restricted namespaces
1405 - if ( $this->isNamespaceProtected() ) {
 1394+ if ( $this->isNamespaceProtected( $user ) ) {
14061395 $ns = $this->mNamespace == NS_MAIN ?
14071396 wfMsg( 'nstab-main' ) : $this->getNsText();
14081397 $errors[] = $this->mNamespace == NS_MEDIAWIKI ?
@@ -1413,7 +1402,14 @@
14141403
14151404 /**
14161405 * Check CSS/JS sub-page permissions
1417 - * @see checkQuickPermissions for parameter information
 1406+ *
 1407+ * @param $action String the action to check
 1408+ * @param $user User user to check
 1409+ * @param $errors Array list of current errors
 1410+ * @param $doExpensiveQueries Boolean whether or not to perform expensive queries
 1411+ * @param $short Boolean short circuit on first error
 1412+ *
 1413+ * @return Array list of errors
14181414 */
14191415 private function checkCSSandJSPermissions( $action, $user, $errors, $doExpensiveQueries, $short ) {
14201416 # Protect css/js subpages of user pages
@@ -1435,7 +1431,14 @@
14361432 * Check against page_restrictions table requirements on this
14371433 * page. The user must possess all required rights for this
14381434 * action.
1439 - * @see checkQuickPermissions for parameter information
 1435+ *
 1436+ * @param $action String the action to check
 1437+ * @param $user User user to check
 1438+ * @param $errors Array list of current errors
 1439+ * @param $doExpensiveQueries Boolean whether or not to perform expensive queries
 1440+ * @param $short Boolean short circuit on first error
 1441+ *
 1442+ * @return Array list of errors
14401443 */
14411444 private function checkPageRestrictions( $action, $user, $errors, $doExpensiveQueries, $short ) {
14421445 foreach ( $this->getRestrictions( $action ) as $right ) {
@@ -1462,7 +1465,14 @@
14631466
14641467 /**
14651468 * Check restrictions on cascading pages.
1466 - * @see checkQuickPermissions for parameter information
 1469+ *
 1470+ * @param $action String the action to check
 1471+ * @param $user User to check
 1472+ * @param $errors Array list of current errors
 1473+ * @param $doExpensiveQueries Boolean whether or not to perform expensive queries
 1474+ * @param $short Boolean short circuit on first error
 1475+ *
 1476+ * @return Array list of errors
14671477 */
14681478 private function checkCascadingSourcesRestrictions( $action, $user, $errors, $doExpensiveQueries, $short ) {
14691479 if ( $doExpensiveQueries && !$this->isCssJsSubpage() ) {
@@ -1494,7 +1504,14 @@
14951505
14961506 /**
14971507 * Check action permissions not already checked in checkQuickPermissions
1498 - * @see checkQuickPermissions for parameter information
 1508+ *
 1509+ * @param $action String the action to check
 1510+ * @param $user User to check
 1511+ * @param $errors Array list of current errors
 1512+ * @param $doExpensiveQueries Boolean whether or not to perform expensive queries
 1513+ * @param $short Boolean short circuit on first error
 1514+ *
 1515+ * @return Array list of errors
14991516 */
15001517 private function checkActionPermissions( $action, $user, $errors, $doExpensiveQueries, $short ) {
15011518 if ( $action == 'protect' ) {
@@ -1535,7 +1552,14 @@
15361553
15371554 /**
15381555 * Check that the user isn't blocked from editting.
1539 - * @see checkQuickPermissions for parameter information
 1556+ *
 1557+ * @param $action String the action to check
 1558+ * @param $user User to check
 1559+ * @param $errors Array list of current errors
 1560+ * @param $doExpensiveQueries Boolean whether or not to perform expensive queries
 1561+ * @param $short Boolean short circuit on first error
 1562+ *
 1563+ * @return Array list of errors
15401564 */
15411565 private function checkUserBlock( $action, $user, $errors, $doExpensiveQueries, $short ) {
15421566 if( !$doExpensiveQueries ) {
@@ -1548,8 +1572,14 @@
15491573 $errors[] = array( 'confirmedittext' );
15501574 }
15511575
1552 - // Edit blocks should not affect reading. Account creation blocks handled at userlogin.
1553 - if ( $action != 'read' && $action != 'createaccount' && $user->isBlockedFrom( $this ) ) {
 1576+ if ( in_array( $action, array( 'read', 'createaccount', 'unblock' ) ) ){
 1577+ // Edit blocks should not affect reading.
 1578+ // Account creation blocks handled at userlogin.
 1579+ // Unblocking handled in SpecialUnblock
 1580+ } elseif( ( $action == 'edit' || $action == 'create' ) && !$user->isBlockedFrom( $this ) ){
 1581+ // Don't block the user from editing their own talk page unless they've been
 1582+ // explicitly blocked from that too.
 1583+ } elseif( $user->isBlocked() && $user->mBlock->prevents( $action ) !== false ) {
15541584 $block = $user->mBlock;
15551585
15561586 // This is from OutputPage::blockedPage
@@ -1569,29 +1599,16 @@
15701600 }
15711601
15721602 $link = '[[' . $wgContLang->getNsText( NS_USER ) . ":{$name}|{$name}]]";
1573 - $blockid = $block->mId;
 1603+ $blockid = $block->getId();
15741604 $blockExpiry = $user->mBlock->mExpiry;
15751605 $blockTimestamp = $wgLang->timeanddate( wfTimestamp( TS_MW, $user->mBlock->mTimestamp ), true );
15761606 if ( $blockExpiry == 'infinity' ) {
1577 - // Entry in database (table ipblocks) is 'infinity' but 'ipboptions' uses 'infinite' or 'indefinite'
1578 - $scBlockExpiryOptions = wfMsg( 'ipboptions' );
1579 -
1580 - foreach ( explode( ',', $scBlockExpiryOptions ) as $option ) {
1581 - if ( !strpos( $option, ':' ) )
1582 - continue;
1583 -
1584 - list( $show, $value ) = explode( ':', $option );
1585 -
1586 - if ( $value == 'infinite' || $value == 'indefinite' ) {
1587 - $blockExpiry = $show;
1588 - break;
1589 - }
1590 - }
 1607+ $blockExpiry = wfMessage( 'infiniteblock' )->text();
15911608 } else {
15921609 $blockExpiry = $wgLang->timeanddate( wfTimestamp( TS_MW, $blockExpiry ), true );
15931610 }
15941611
1595 - $intended = $user->mBlock->mAddress;
 1612+ $intended = strval( $user->mBlock->getTarget() );
15961613
15971614 $errors[] = array( ( $block->mAuto ? 'autoblockedtext' : 'blockedtext' ), $link, $reason, $ip, $name,
15981615 $blockid, $blockExpiry, $intended, $blockTimestamp );
@@ -1605,11 +1622,11 @@
16061623 * which checks ONLY that previously checked by userCan (i.e. it leaves out
16071624 * checks on wfReadOnly() and blocks)
16081625 *
1609 - * @param $action \type{\string} action that permission needs to be checked for
1610 - * @param $user \type{User} user to check
1611 - * @param $doExpensiveQueries \type{\bool} Set this to false to avoid doing unnecessary queries.
1612 - * @param $short \type{\bool} Set this to true to stop after the first permission error.
1613 - * @return \type{\array} Array of arrays of the arguments to wfMsg to explain permissions problems.
 1626+ * @param $action String action that permission needs to be checked for
 1627+ * @param $user User to check
 1628+ * @param $doExpensiveQueries Bool Set this to false to avoid doing unnecessary queries.
 1629+ * @param $short Bool Set this to true to stop after the first permission error.
 1630+ * @return Array of arrays of the arguments to wfMsg to explain permissions problems.
16141631 */
16151632 protected function getUserPermissionsErrorsInternal( $action, $user, $doExpensiveQueries = true, $short = false ) {
16161633 wfProfileIn( __METHOD__ );
@@ -1638,8 +1655,9 @@
16391656
16401657 /**
16411658 * Is this title subject to title protection?
 1659+ * Title protection is the one applied against creation of such title.
16421660 *
1643 - * @return \type{\mixed} An associative array representing any existent title
 1661+ * @return Mixed An associative array representing any existent title
16441662 * protection, or false if there's none.
16451663 */
16461664 private function getTitleProtection() {
@@ -1668,9 +1686,9 @@
16691687 /**
16701688 * Update the title protection status
16711689 *
1672 - * @param $create_perm \type{\string} Permission required for creation
1673 - * @param $reason \type{\string} Reason for protection
1674 - * @param $expiry \type{\string} Expiry timestamp
 1690+ * @param $create_perm String Permission required for creation
 1691+ * @param $reason String Reason for protection
 1692+ * @param $expiry String Expiry timestamp
16751693 * @return boolean true
16761694 */
16771695 public function updateTitleProtection( $create_perm, $reason, $expiry ) {
@@ -1686,10 +1704,10 @@
16871705
16881706 $dbw = wfGetDB( DB_MASTER );
16891707
1690 - $encodedExpiry = Block::encodeExpiry( $expiry, $dbw );
 1708+ $encodedExpiry = $dbw->encodeExpiry( $expiry );
16911709
16921710 $expiry_description = '';
1693 - if ( $encodedExpiry != 'infinity' ) {
 1711+ if ( $encodedExpiry != $dbw->getInfinity() ) {
16941712 $expiry_description = ' (' . wfMsgForContent( 'protect-expiring', $wgContLang->timeanddate( $expiry ),
16951713 $wgContLang->date( $expiry ) , $wgContLang->time( $expiry ) ) . ')';
16961714 } else {
@@ -1698,21 +1716,23 @@
16991717
17001718 # Update protection table
17011719 if ( $create_perm != '' ) {
1702 - $dbw->replace( 'protected_titles', array( array( 'pt_namespace', 'pt_title' ) ),
1703 - array(
 1720+ $this->mTitleProtection = array(
17041721 'pt_namespace' => $namespace,
17051722 'pt_title' => $title,
17061723 'pt_create_perm' => $create_perm,
1707 - 'pt_timestamp' => Block::encodeExpiry( wfTimestampNow(), $dbw ),
 1724+ 'pt_timestamp' => $dbw->encodeExpiry( wfTimestampNow() ),
17081725 'pt_expiry' => $encodedExpiry,
17091726 'pt_user' => $wgUser->getId(),
17101727 'pt_reason' => $reason,
1711 - ), __METHOD__
1712 - );
 1728+ );
 1729+ $dbw->replace( 'protected_titles', array( array( 'pt_namespace', 'pt_title' ) ),
 1730+ $this->mTitleProtection, __METHOD__ );
17131731 } else {
17141732 $dbw->delete( 'protected_titles', array( 'pt_namespace' => $namespace,
17151733 'pt_title' => $title ), __METHOD__ );
 1734+ $this->mTitleProtection = false;
17161735 }
 1736+
17171737 # Update the protection log
17181738 if ( $dbw->affectedRows() ) {
17191739 $log = new LogPage( 'protect' );
@@ -1739,13 +1759,14 @@
17401760 array( 'pt_namespace' => $this->getNamespace(), 'pt_title' => $this->getDBkey() ),
17411761 __METHOD__
17421762 );
 1763+ $this->mTitleProtection = false;
17431764 }
17441765
17451766 /**
17461767 * Would anybody with sufficient privileges be able to move this page?
17471768 * Some pages just aren't movable.
17481769 *
1749 - * @return \type{\bool} TRUE or FALSE
 1770+ * @return Bool TRUE or FALSE
17501771 */
17511772 public function isMovable() {
17521773 return MWNamespace::isMovable( $this->getNamespace() ) && $this->getInterwiki() == '';
@@ -1754,7 +1775,7 @@
17551776 /**
17561777 * Can $wgUser read this page?
17571778 *
1758 - * @return \type{\bool}
 1779+ * @return Bool
17591780 * @todo fold these checks into userCan()
17601781 */
17611782 public function userCanRead() {
@@ -1802,47 +1823,36 @@
18031824 } else {
18041825 global $wgWhitelistRead;
18051826
1806 - /**
1807 - * Always grant access to the login page.
1808 - * Even anons need to be able to log in.
1809 - */
1810 - if ( $this->isSpecial( 'Userlogin' ) || $this->isSpecial( 'Resetpass' ) ) {
 1827+ # Always grant access to the login page.
 1828+ # Even anons need to be able to log in.
 1829+ if ( $this->isSpecial( 'Userlogin' ) || $this->isSpecial( 'ChangePassword' ) ) {
18111830 return true;
18121831 }
18131832
1814 - /**
1815 - * Bail out if there isn't whitelist
1816 - */
 1833+ # Bail out if there isn't whitelist
18171834 if ( !is_array( $wgWhitelistRead ) ) {
18181835 return false;
18191836 }
18201837
1821 - /**
1822 - * Check for explicit whitelisting
1823 - */
 1838+ # Check for explicit whitelisting
18241839 $name = $this->getPrefixedText();
18251840 $dbName = $this->getPrefixedDBKey();
18261841 // Check with and without underscores
18271842 if ( in_array( $name, $wgWhitelistRead, true ) || in_array( $dbName, $wgWhitelistRead, true ) )
18281843 return true;
18291844
1830 - /**
1831 - * Old settings might have the title prefixed with
1832 - * a colon for main-namespace pages
1833 - */
 1845+ # Old settings might have the title prefixed with
 1846+ # a colon for main-namespace pages
18341847 if ( $this->getNamespace() == NS_MAIN ) {
18351848 if ( in_array( ':' . $name, $wgWhitelistRead ) ) {
18361849 return true;
18371850 }
18381851 }
18391852
1840 - /**
1841 - * If it's a special page, ditch the subpage bit
1842 - * and check again
1843 - */
 1853+ # If it's a special page, ditch the subpage bit and check again
18441854 if ( $this->getNamespace() == NS_SPECIAL ) {
18451855 $name = $this->getDBkey();
1846 - list( $name, /* $subpage */ ) = SpecialPage::resolveAliasWithSubpage( $name );
 1856+ list( $name, /* $subpage */ ) = SpecialPageFactory::resolveAlias( $name );
18471857 if ( $name === false ) {
18481858 # Invalid special page, but we show standard login required message
18491859 return false;
@@ -1859,9 +1869,22 @@
18601870 }
18611871
18621872 /**
 1873+ * Is this the mainpage?
 1874+ * @note Title::newFromText seams to be sufficiently optimized by the title
 1875+ * cache that we don't need to over-optimize by doing direct comparisons and
 1876+ * acidentally creating new bugs where $title->equals( Title::newFromText() )
 1877+ * ends up reporting something differently than $title->isMainPage();
 1878+ *
 1879+ * @return Bool
 1880+ */
 1881+ public function isMainPage() {
 1882+ return $this->equals( Title::newMainPage() );
 1883+ }
 1884+
 1885+ /**
18631886 * Is this a talk page of some sort?
18641887 *
1865 - * @return \type{\bool}
 1888+ * @return Bool
18661889 */
18671890 public function isTalkPage() {
18681891 return MWNamespace::isTalk( $this->getNamespace() );
@@ -1870,7 +1893,7 @@
18711894 /**
18721895 * Is this a subpage?
18731896 *
1874 - * @return \type{\bool}
 1897+ * @return Bool
18751898 */
18761899 public function isSubpage() {
18771900 return MWNamespace::hasSubpages( $this->mNamespace )
@@ -1881,7 +1904,7 @@
18821905 /**
18831906 * Does this have subpages? (Warning, usually requires an extra DB query.)
18841907 *
1885 - * @return \type{\bool}
 1908+ * @return Bool
18861909 */
18871910 public function hasSubpages() {
18881911 if ( !MWNamespace::hasSubpages( $this->mNamespace ) ) {
@@ -1907,7 +1930,7 @@
19081931 /**
19091932 * Get all subpages of this page.
19101933 *
1911 - * @param $limit Maximum number of subpages to fetch; -1 for no limit
 1934+ * @param $limit Int maximum number of subpages to fetch; -1 for no limit
19121935 * @return mixed TitleArray, or empty array if this page's namespace
19131936 * doesn't allow subpages
19141937 */
@@ -1937,7 +1960,7 @@
19381961 * Could this page contain custom CSS or JavaScript, based
19391962 * on the title?
19401963 *
1941 - * @return \type{\bool}
 1964+ * @return Bool
19421965 */
19431966 public function isCssOrJsPage() {
19441967 return $this->mNamespace == NS_MEDIAWIKI
@@ -1946,7 +1969,7 @@
19471970
19481971 /**
19491972 * Is this a .css or .js subpage of a user page?
1950 - * @return \type{\bool}
 1973+ * @return Bool
19511974 */
19521975 public function isCssJsSubpage() {
19531976 return ( NS_USER == $this->mNamespace and preg_match( "/\\/.*\\.(?:css|js)$/", $this->mTextform ) );
@@ -1954,21 +1977,12 @@
19551978
19561979 /**
19571980 * Is this a *valid* .css or .js subpage of a user page?
1958 - * Check that the corresponding skin exists
19591981 *
1960 - * @return \type{\bool}
 1982+ * @return Bool
 1983+ * @deprecated since 1.17
19611984 */
19621985 public function isValidCssJsSubpage() {
1963 - if ( $this->isCssJsSubpage() ) {
1964 - $name = $this->getSkinFromCssJsSubpage();
1965 - if ( $name == 'common' ) {
1966 - return true;
1967 - }
1968 - $skinNames = Skin::getSkinNames();
1969 - return array_key_exists( $name, $skinNames );
1970 - } else {
1971 - return false;
1972 - }
 1986+ return $this->isCssJsSubpage();
19731987 }
19741988
19751989 /**
@@ -1985,7 +1999,7 @@
19862000 /**
19872001 * Is this a .css subpage of a user page?
19882002 *
1989 - * @return \type{\bool}
 2003+ * @return Bool
19902004 */
19912005 public function isCssSubpage() {
19922006 return ( NS_USER == $this->mNamespace && preg_match( "/\\/.*\\.css$/", $this->mTextform ) );
@@ -1994,7 +2008,7 @@
19952009 /**
19962010 * Is this a .js subpage of a user page?
19972011 *
1998 - * @return \type{\bool}
 2012+ * @return Bool
19992013 */
20002014 public function isJsSubpage() {
20012015 return ( NS_USER == $this->mNamespace && preg_match( "/\\/.*\\.js$/", $this->mTextform ) );
@@ -2031,7 +2045,7 @@
20322046 /**
20332047 * Cascading protection: Return true if cascading restrictions apply to this page, false if not.
20342048 *
2035 - * @return \type{\bool} If the page is subject to cascading restrictions.
 2049+ * @return Bool If the page is subject to cascading restrictions.
20362050 */
20372051 public function isCascadeProtected() {
20382052 list( $sources, /* $restrictions */ ) = $this->getCascadeProtectionSources( false );
@@ -2041,15 +2055,15 @@
20422056 /**
20432057 * Cascading protection: Get the source of any cascading restrictions on this page.
20442058 *
2045 - * @param $getPages \type{\bool} Whether or not to retrieve the actual pages
 2059+ * @param $getPages Bool Whether or not to retrieve the actual pages
20462060 * that the restrictions have come from.
2047 - * @return \type{\arrayof{mixed title array, restriction array}} Array of the Title
2048 - * objects of the pages from which cascading restrictions have come,
2049 - * false for none, or true if such restrictions exist, but $getPages was not set.
2050 - * The restriction array is an array of each type, each of which contains a
2051 - * array of unique groups.
 2061+ * @return Mixed Array of Title objects of the pages from which cascading restrictions
 2062+ * have come, false for none, or true if such restrictions exist, but $getPages
 2063+ * was not set. The restriction array is an array of each type, each of which
 2064+ * contains a array of unique groups.
20522065 */
20532066 public function getCascadeProtectionSources( $getPages = true ) {
 2067+ global $wgContLang;
20542068 $pagerestrictions = array();
20552069
20562070 if ( isset( $this->mCascadeSources ) && $getPages ) {
@@ -2095,7 +2109,7 @@
20962110 $purgeExpired = false;
20972111
20982112 foreach ( $res as $row ) {
2099 - $expiry = Block::decodeExpiry( $row->pr_expiry );
 2113+ $expiry = $wgContLang->formatExpiry( $row->pr_expiry, TS_MW );
21002114 if ( $expiry > $now ) {
21012115 if ( $getPages ) {
21022116 $page_id = $row->pr_page;
@@ -2125,8 +2139,6 @@
21262140 Title::purgeExpiredRestrictions();
21272141 }
21282142
2129 - wfProfileOut( __METHOD__ );
2130 -
21312143 if ( $getPages ) {
21322144 $this->mCascadeSources = $sources;
21332145 $this->mCascadingRestrictions = $pagerestrictions;
@@ -2134,6 +2146,7 @@
21352147 $this->mHasCascadingRestrictions = $sources;
21362148 }
21372149
 2150+ wfProfileOut( __METHOD__ );
21382151 return array( $sources, $pagerestrictions );
21392152 }
21402153
@@ -2153,15 +2166,14 @@
21542167 /**
21552168 * Loads a string into mRestrictions array
21562169 *
2157 - * @param $res \type{Resource} restrictions as an SQL result.
2158 - * @param $oldFashionedRestrictions string comma-separated list of page
 2170+ * @param $res Resource restrictions as an SQL result.
 2171+ * @param $oldFashionedRestrictions String comma-separated list of page
21592172 * restrictions from page table (pre 1.10)
21602173 */
21612174 private function loadRestrictionsFromResultWrapper( $res, $oldFashionedRestrictions = null ) {
21622175 $rows = array();
2163 - $dbr = wfGetDB( DB_SLAVE );
21642176
2165 - while ( $row = $dbr->fetchObject( $res ) ) {
 2177+ foreach ( $res as $row ) {
21662178 $rows[] = $row;
21672179 }
21682180
@@ -2170,20 +2182,22 @@
21712183
21722184 /**
21732185 * Compiles list of active page restrictions from both page table (pre 1.10)
2174 - * and page_restrictions table
 2186+ * and page_restrictions table for this existing page.
 2187+ * Public for usage by LiquidThreads.
21752188 *
21762189 * @param $rows array of db result objects
21772190 * @param $oldFashionedRestrictions string comma-separated list of page
21782191 * restrictions from page table (pre 1.10)
21792192 */
21802193 public function loadRestrictionsFromRows( $rows, $oldFashionedRestrictions = null ) {
 2194+ global $wgContLang;
21812195 $dbr = wfGetDB( DB_SLAVE );
21822196
21832197 $restrictionTypes = $this->getRestrictionTypes();
21842198
21852199 foreach ( $restrictionTypes as $type ) {
21862200 $this->mRestrictions[$type] = array();
2187 - $this->mRestrictionsExpiry[$type] = Block::decodeExpiry( '' );
 2201+ $this->mRestrictionsExpiry[$type] = $wgContLang->formatExpiry( '', TS_MW );
21882202 }
21892203
21902204 $this->mCascadeRestriction = false;
@@ -2217,17 +2231,16 @@
22182232 $now = wfTimestampNow();
22192233 $purgeExpired = false;
22202234
 2235+ # Cycle through all the restrictions.
22212236 foreach ( $rows as $row ) {
2222 - # Cycle through all the restrictions.
22232237
22242238 // Don't take care of restrictions types that aren't allowed
2225 -
22262239 if ( !in_array( $row->pr_type, $restrictionTypes ) )
22272240 continue;
22282241
22292242 // This code should be refactored, now that it's being used more generally,
22302243 // But I don't really see any harm in leaving it in Block for now -werdna
2231 - $expiry = Block::decodeExpiry( $row->pr_expiry );
 2244+ $expiry = $wgContLang->formatExpiry( $row->pr_expiry, TS_MW );
22322245
22332246 // Only apply the restrictions if they haven't expired!
22342247 if ( !$expiry || $expiry > $now ) {
@@ -2252,16 +2265,21 @@
22532266 /**
22542267 * Load restrictions from the page_restrictions table
22552268 *
2256 - * @param $oldFashionedRestrictions string comma-separated list of page
 2269+ * @param $oldFashionedRestrictions String comma-separated list of page
22572270 * restrictions from page table (pre 1.10)
22582271 */
22592272 public function loadRestrictions( $oldFashionedRestrictions = null ) {
 2273+ global $wgContLang;
22602274 if ( !$this->mRestrictionsLoaded ) {
22612275 if ( $this->exists() ) {
22622276 $dbr = wfGetDB( DB_SLAVE );
22632277
2264 - $res = $dbr->select( 'page_restrictions', '*',
2265 - array( 'pr_page' => $this->getArticleId() ), __METHOD__ );
 2278+ $res = $dbr->select(
 2279+ 'page_restrictions',
 2280+ '*',
 2281+ array( 'pr_page' => $this->getArticleId() ),
 2282+ __METHOD__
 2283+ );
22662284
22672285 $this->loadRestrictionsFromResultWrapper( $res, $oldFashionedRestrictions );
22682286 } else {
@@ -2269,7 +2287,7 @@
22702288
22712289 if ( $title_protection ) {
22722290 $now = wfTimestampNow();
2273 - $expiry = Block::decodeExpiry( $title_protection['pt_expiry'] );
 2291+ $expiry = $wgContLang->formatExpiry( $title_protection['pt_expiry'], TS_MW );
22742292
22752293 if ( !$expiry || $expiry > $now ) {
22762294 // Apply the restrictions
@@ -2277,9 +2295,10 @@
22782296 $this->mRestrictions['create'] = explode( ',', trim( $title_protection['pt_create_perm'] ) );
22792297 } else { // Get rid of the old restrictions
22802298 Title::purgeExpiredRestrictions();
 2299+ $this->mTitleProtection = false;
22812300 }
22822301 } else {
2283 - $this->mRestrictionsExpiry['create'] = Block::decodeExpiry( '' );
 2302+ $this->mRestrictionsExpiry['create'] = $wgContLang->formatExpiry( '', TS_MW );
22842303 }
22852304 $this->mRestrictionsLoaded = true;
22862305 }
@@ -2307,8 +2326,8 @@
23082327 /**
23092328 * Accessor/initialisation for mRestrictions
23102329 *
2311 - * @param $action \type{\string} action that permission needs to be checked for
2312 - * @return \type{\arrayof{\string}} the array of groups allowed to edit this article
 2330+ * @param $action String action that permission needs to be checked for
 2331+ * @return Array of Strings the array of groups allowed to edit this article
23132332 */
23142333 public function getRestrictions( $action ) {
23152334 if ( !$this->mRestrictionsLoaded ) {
@@ -2322,7 +2341,7 @@
23232342 /**
23242343 * Get the expiry time for the restriction against a given action
23252344 *
2326 - * @return 14-char timestamp, or 'infinity' if the page is protected forever
 2345+ * @return String|Bool 14-char timestamp, or 'infinity' if the page is protected forever
23272346 * or not protected at all, or false if the action is not recognised.
23282347 */
23292348 public function getRestrictionExpiry( $action ) {
@@ -2400,16 +2419,16 @@
24012420 * Get the article ID for this Title from the link cache,
24022421 * adding it if necessary
24032422 *
2404 - * @param $flags \type{\int} a bit field; may be GAID_FOR_UPDATE to select
 2423+ * @param $flags Int a bit field; may be Title::GAID_FOR_UPDATE to select
24052424 * for update
2406 - * @return \type{\int} the ID
 2425+ * @return Int the ID
24072426 */
24082427 public function getArticleID( $flags = 0 ) {
24092428 if ( $this->getNamespace() < 0 ) {
24102429 return $this->mArticleID = 0;
24112430 }
24122431 $linkCache = LinkCache::singleton();
2413 - if ( $flags & GAID_FOR_UPDATE ) {
 2432+ if ( $flags & self::GAID_FOR_UPDATE ) {
24142433 $oldUpdate = $linkCache->forUpdate( true );
24152434 $linkCache->clearLink( $this );
24162435 $this->mArticleID = $linkCache->addLinkObj( $this );
@@ -2426,8 +2445,8 @@
24272446 * Is this an article that is a redirect page?
24282447 * Uses link cache, adding it if necessary
24292448 *
2430 - * @param $flags \type{\int} a bit field; may be GAID_FOR_UPDATE to select for update
2431 - * @return \type{\bool}
 2449+ * @param $flags Int a bit field; may be Title::GAID_FOR_UPDATE to select for update
 2450+ * @return Bool
24322451 */
24332452 public function isRedirect( $flags = 0 ) {
24342453 if ( !is_null( $this->mRedirect ) ) {
@@ -2447,8 +2466,8 @@
24482467 * What is the length of this page?
24492468 * Uses link cache, adding it if necessary
24502469 *
2451 - * @param $flags \type{\int} a bit field; may be GAID_FOR_UPDATE to select for update
2452 - * @return \type{\bool}
 2470+ * @param $flags Int a bit field; may be Title::GAID_FOR_UPDATE to select for update
 2471+ * @return Int
24532472 */
24542473 public function getLength( $flags = 0 ) {
24552474 if ( $this->mLength != -1 ) {
@@ -2467,8 +2486,8 @@
24682487 /**
24692488 * What is the page_latest field for this page?
24702489 *
2471 - * @param $flags \type{\int} a bit field; may be GAID_FOR_UPDATE to select for update
2472 - * @return \type{\int} or 0 if the page doesn't exist
 2490+ * @param $flags Int a bit field; may be Title::GAID_FOR_UPDATE to select for update
 2491+ * @return Int or 0 if the page doesn't exist
24732492 */
24742493 public function getLatestRevID( $flags = 0 ) {
24752494 if ( $this->mLatestID !== false ) {
@@ -2488,7 +2507,11 @@
24892508 * This clears some fields in this object, and clears any associated
24902509 * keys in the "bad links" section of the link cache.
24912510 *
2492 - * @param $newid \type{\int} the new Article ID
 2511+ * - This is called from Article::doEdit() and Article::insertOn() to allow
 2512+ * loading of the new page_id. It's also called from
 2513+ * Article::doDeleteArticle()
 2514+ *
 2515+ * @param $newid Int the new Article ID
24932516 */
24942517 public function resetArticleID( $newid ) {
24952518 $linkCache = LinkCache::singleton();
@@ -2509,7 +2532,7 @@
25102533 /**
25112534 * Updates page_touched for this page; called from LinksUpdate.php
25122535 *
2513 - * @return \type{\bool} true if the update succeded
 2536+ * @return Bool true if the update succeded
25142537 */
25152538 public function invalidateCache() {
25162539 if ( wfReadOnly() ) {
@@ -2530,15 +2553,16 @@
25312554 * Prefix some arbitrary text with the namespace or interwiki prefix
25322555 * of this object
25332556 *
2534 - * @param $name \type{\string} the text
2535 - * @return \type{\string} the prefixed text
 2557+ * @param $name String the text
 2558+ * @return String the prefixed text
25362559 * @private
25372560 */
2538 - /* private */ function prefix( $name ) {
 2561+ private function prefix( $name ) {
25392562 $p = '';
25402563 if ( $this->mInterwiki != '' ) {
25412564 $p = $this->mInterwiki . ':';
25422565 }
 2566+
25432567 if ( 0 != $this->mNamespace ) {
25442568 $p .= $this->getNsText() . ':';
25452569 }
@@ -2550,7 +2574,7 @@
25512575 * Note that this doesn't pick up many things that could be wrong with titles, but that
25522576 * replacing this regex with something valid will make many titles valid.
25532577 *
2554 - * @return string regex string
 2578+ * @return String regex string
25552579 */
25562580 static function getTitleInvalidRegex() {
25572581 static $rxTc = false;
@@ -2575,7 +2599,7 @@
25762600 /**
25772601 * Capitalize a text string for a title if it belongs to a namespace that capitalizes
25782602 *
2579 - * @param $text string containing title to capitalize
 2603+ * @param $text String containing title to capitalize
25802604 * @param $ns int namespace index, defaults to NS_MAIN
25812605 * @return String containing capitalized title
25822606 */
@@ -2598,14 +2622,12 @@
25992623 * namespace prefixes, sets the other forms, and canonicalizes
26002624 * everything.
26012625 *
2602 - * @return \type{\bool} true on success
 2626+ * @return Bool true on success
26032627 */
26042628 private function secureAndSplit() {
26052629 global $wgContLang, $wgLocalInterwiki;
26062630
26072631 # Initialisation
2608 - $rxTc = self::getTitleInvalidRegex();
2609 -
26102632 $this->mInterwiki = $this->mFragment = '';
26112633 $this->mNamespace = $this->mDefaultNamespace; # Usually NS_MAIN
26122634
@@ -2620,7 +2642,6 @@
26212643 # Note: use of the /u option on preg_replace here will cause
26222644 # input with invalid UTF-8 sequences to be nullified out in PHP 5.2.x,
26232645 # conveniently disabling them.
2624 - #
26252646 $dbkey = preg_replace( '/[ _\xA0\x{1680}\x{180E}\x{2000}-\x{200A}\x{2028}\x{2029}\x{202F}\x{205F}\x{3000}]+/u', '_', $dbkey );
26262647 $dbkey = trim( $dbkey, '_' );
26272648
@@ -2657,9 +2678,11 @@
26582679 # For Talk:X pages, check if X has a "namespace" prefix
26592680 if ( $ns == NS_TALK && preg_match( $prefixRegexp, $dbkey, $x ) ) {
26602681 if ( $wgContLang->getNsIndex( $x[1] ) ) {
2661 - return false; # Disallow Talk:File:x type titles...
 2682+ # Disallow Talk:File:x type titles...
 2683+ return false;
26622684 } elseif ( Interwiki::isValidInterwiki( $x[1] ) ) {
2663 - return false; # Disallow Talk:Interwiki:x type titles...
 2685+ # Disallow Talk:Interwiki:x type titles...
 2686+ return false;
26642687 }
26652688 }
26662689 } elseif ( Interwiki::isValidInterwiki( $p ) ) {
@@ -2674,7 +2697,9 @@
26752698 $this->mInterwiki = $wgContLang->lc( $p );
26762699
26772700 # Redundant interwiki prefix to the local wiki
2678 - if ( 0 == strcasecmp( $this->mInterwiki, $wgLocalInterwiki ) ) {
 2701+ if ( $wgLocalInterwiki !== false
 2702+ && 0 == strcasecmp( $this->mInterwiki, $wgLocalInterwiki ) )
 2703+ {
26792704 if ( $dbkey == '' ) {
26802705 # Can't have an empty self-link
26812706 return false;
@@ -2699,13 +2724,12 @@
27002725 } while ( true );
27012726
27022727 # We already know that some pages won't be in the database!
2703 - #
27042728 if ( $this->mInterwiki != '' || NS_SPECIAL == $this->mNamespace ) {
27052729 $this->mArticleID = 0;
27062730 }
27072731 $fragment = strstr( $dbkey, '#' );
27082732 if ( false !== $fragment ) {
2709 - $this->setFragment( preg_replace( '/^#_*/', '#', $fragment ) );
 2733+ $this->setFragment( $fragment );
27102734 $dbkey = substr( $dbkey, 0, strlen( $dbkey ) - strlen( $fragment ) );
27112735 # remove whitespace again: prevents "Foo_bar_#"
27122736 # becoming "Foo_bar_"
@@ -2713,79 +2737,65 @@
27142738 }
27152739
27162740 # Reject illegal characters.
2717 - #
 2741+ $rxTc = self::getTitleInvalidRegex();
27182742 if ( preg_match( $rxTc, $dbkey ) ) {
27192743 return false;
27202744 }
27212745
2722 - /**
2723 - * Pages with "/./" or "/../" appearing in the URLs will often be un-
2724 - * reachable due to the way web browsers deal with 'relative' URLs.
2725 - * Also, they conflict with subpage syntax. Forbid them explicitly.
2726 - */
 2746+ # Pages with "/./" or "/../" appearing in the URLs will often be un-
 2747+ # reachable due to the way web browsers deal with 'relative' URLs.
 2748+ # Also, they conflict with subpage syntax. Forbid them explicitly.
27272749 if ( strpos( $dbkey, '.' ) !== false &&
2728 - ( $dbkey === '.' || $dbkey === '..' ||
2729 - strpos( $dbkey, './' ) === 0 ||
2730 - strpos( $dbkey, '../' ) === 0 ||
2731 - strpos( $dbkey, '/./' ) !== false ||
2732 - strpos( $dbkey, '/../' ) !== false ||
2733 - substr( $dbkey, -2 ) == '/.' ||
2734 - substr( $dbkey, -3 ) == '/..' ) )
 2750+ ( $dbkey === '.' || $dbkey === '..' ||
 2751+ strpos( $dbkey, './' ) === 0 ||
 2752+ strpos( $dbkey, '../' ) === 0 ||
 2753+ strpos( $dbkey, '/./' ) !== false ||
 2754+ strpos( $dbkey, '/../' ) !== false ||
 2755+ substr( $dbkey, -2 ) == '/.' ||
 2756+ substr( $dbkey, -3 ) == '/..' ) )
27352757 {
27362758 return false;
27372759 }
27382760
2739 - /**
2740 - * Magic tilde sequences? Nu-uh!
2741 - */
 2761+ # Magic tilde sequences? Nu-uh!
27422762 if ( strpos( $dbkey, '~~~' ) !== false ) {
27432763 return false;
27442764 }
27452765
2746 - /**
2747 - * Limit the size of titles to 255 bytes.
2748 - * This is typically the size of the underlying database field.
2749 - * We make an exception for special pages, which don't need to be stored
2750 - * in the database, and may edge over 255 bytes due to subpage syntax
2751 - * for long titles, e.g. [[Special:Block/Long name]]
2752 - */
 2766+ # Limit the size of titles to 255 bytes. This is typically the size of the
 2767+ # underlying database field. We make an exception for special pages, which
 2768+ # don't need to be stored in the database, and may edge over 255 bytes due
 2769+ # to subpage syntax for long titles, e.g. [[Special:Block/Long name]]
27532770 if ( ( $this->mNamespace != NS_SPECIAL && strlen( $dbkey ) > 255 ) ||
27542771 strlen( $dbkey ) > 512 )
27552772 {
27562773 return false;
27572774 }
27582775
2759 - /**
2760 - * Normally, all wiki links are forced to have
2761 - * an initial capital letter so [[foo]] and [[Foo]]
2762 - * point to the same place.
2763 - *
2764 - * Don't force it for interwikis, since the other
2765 - * site might be case-sensitive.
2766 - */
 2776+ # Normally, all wiki links are forced to have an initial capital letter so [[foo]]
 2777+ # and [[Foo]] point to the same place. Don't force it for interwikis, since the
 2778+ # other site might be case-sensitive.
27672779 $this->mUserCaseDBKey = $dbkey;
27682780 if ( $this->mInterwiki == '' ) {
27692781 $dbkey = self::capitalize( $dbkey, $this->mNamespace );
27702782 }
27712783
2772 - /**
2773 - * Can't make a link to a namespace alone...
2774 - * "empty" local links can only be self-links
2775 - * with a fragment identifier.
2776 - */
2777 - if ( $dbkey == '' &&
2778 - $this->mInterwiki == '' &&
2779 - $this->mNamespace != NS_MAIN ) {
 2784+ # Can't make a link to a namespace alone... "empty" local links can only be
 2785+ # self-links with a fragment identifier.
 2786+ if ( $dbkey == '' && $this->mInterwiki == '' && $this->mNamespace != NS_MAIN ) {
27802787 return false;
27812788 }
 2789+
27822790 // Allow IPv6 usernames to start with '::' by canonicalizing IPv6 titles.
27832791 // IP names are not allowed for accounts, and can only be referring to
27842792 // edits from the IP. Given '::' abbreviations and caps/lowercaps,
27852793 // there are numerous ways to present the same IP. Having sp:contribs scan
27862794 // them all is silly and having some show the edits and others not is
27872795 // inconsistent. Same for talk/userpages. Keep them normalized instead.
2788 - $dbkey = ( $this->mNamespace == NS_USER || $this->mNamespace == NS_USER_TALK ) ?
2789 - IP::sanitizeIP( $dbkey ) : $dbkey;
 2796+ $dbkey = ( $this->mNamespace == NS_USER || $this->mNamespace == NS_USER_TALK )
 2797+ ? IP::sanitizeIP( $dbkey )
 2798+ : $dbkey;
 2799+
27902800 // Any remaining initial :s are illegal.
27912801 if ( $dbkey !== '' && ':' == $dbkey { 0 } ) {
27922802 return false;
@@ -2808,7 +2818,7 @@
28092819 * Deprecated for public use, use Title::makeTitle() with fragment parameter.
28102820 * Still in active use privately.
28112821 *
2812 - * @param $fragment \type{\string} text
 2822+ * @param $fragment String text
28132823 */
28142824 public function setFragment( $fragment ) {
28152825 $this->mFragment = str_replace( '_', ' ', substr( $fragment, 1 ) );
@@ -2821,7 +2831,7 @@
28222832 /**
28232833 * Get a Title object associated with the talk page of this article
28242834 *
2825 - * @return \type{Title} the object for the talk page
 2835+ * @return Title the object for the talk page
28262836 */
28272837 public function getTalkPage() {
28282838 return Title::makeTitle( MWNamespace::getTalk( $this->getNamespace() ), $this->getDBkey() );
@@ -2831,7 +2841,7 @@
28322842 * Get a title object associated with the subject page of this
28332843 * talk page
28342844 *
2835 - * @return \type{Title} the object for the subject page
 2845+ * @return Title the object for the subject page
28362846 */
28372847 public function getSubjectPage() {
28382848 // Is this the same title?
@@ -2852,7 +2862,7 @@
28532863 * @param $options Array: may be FOR UPDATE
28542864 * @param $table String: table name
28552865 * @param $prefix String: fields prefix
2856 - * @return \type{\arrayof{Title}} the Title objects linking here
 2866+ * @return Array of Title objects linking here
28572867 */
28582868 public function getLinksTo( $options = array(), $table = 'pagelinks', $prefix = 'pl' ) {
28592869 $linkCache = LinkCache::singleton();
@@ -2877,13 +2887,13 @@
28782888 $retVal = array();
28792889 if ( $db->numRows( $res ) ) {
28802890 foreach ( $res as $row ) {
2881 - if ( $titleObj = Title::makeTitle( $row->page_namespace, $row->page_title ) ) {
 2891+ $titleObj = Title::makeTitle( $row->page_namespace, $row->page_title );
 2892+ if ( $titleObj ) {
28822893 $linkCache->addGoodLinkObj( $row->page_id, $titleObj, $row->page_len, $row->page_is_redirect, $row->page_latest );
28832894 $retVal[] = $titleObj;
28842895 }
28852896 }
28862897 }
2887 - $db->freeResult( $res );
28882898 return $retVal;
28892899 }
28902900
@@ -2895,7 +2905,7 @@
28962906 * On heavily-used templates it will max out the memory.
28972907 *
28982908 * @param $options Array: may be FOR UPDATE
2899 - * @return \type{\arrayof{Title}} the Title objects linking here
 2909+ * @return Array of Title the Title objects linking here
29002910 */
29012911 public function getTemplateLinksTo( $options = array() ) {
29022912 return $this->getLinksTo( $options, 'templatelinks', 'tl' );
@@ -2905,7 +2915,7 @@
29062916 * Get an array of Title objects referring to non-existent articles linked from this page
29072917 *
29082918 * @todo check if needed (used only in SpecialBrokenRedirects.php, and should use redirect table in this case)
2909 - * @return \type{\arrayof{Title}} the Title objects
 2919+ * @return Array of Title the Title objects
29102920 */
29112921 public function getBrokenLinksFrom() {
29122922 if ( $this->getArticleId() == 0 ) {
@@ -2942,7 +2952,7 @@
29432953 * Get a list of URLs to purge from the Squid cache when this
29442954 * page changes
29452955 *
2946 - * @return \type{\arrayof{\string}} the URLs
 2956+ * @return Array of String the URLs
29472957 */
29482958 public function getSquidURLs() {
29492959 global $wgContLang;
@@ -2978,8 +2988,8 @@
29792989 /**
29802990 * Move this page without authentication
29812991 *
2982 - * @param $nt \type{Title} the new page Title
2983 - * @return \type{\mixed} true on success, getUserPermissionsErrors()-like array on failure
 2992+ * @param $nt Title the new page Title
 2993+ * @return Mixed true on success, getUserPermissionsErrors()-like array on failure
29842994 */
29852995 public function moveNoAuth( &$nt ) {
29862996 return $this->moveTo( $nt, false );
@@ -2989,11 +2999,11 @@
29903000 * Check whether a given move operation would be valid.
29913001 * Returns true if ok, or a getUserPermissionsErrors()-like array otherwise
29923002 *
2993 - * @param $nt \type{Title} the new title
2994 - * @param $auth \type{\bool} indicates whether $wgUser's permissions
 3003+ * @param $nt Title the new title
 3004+ * @param $auth Bool indicates whether $wgUser's permissions
29953005 * should be checked
2996 - * @param $reason \type{\string} is the log summary of the move, used for spam checking
2997 - * @return \type{\mixed} True on success, getUserPermissionsErrors()-like array on failure
 3006+ * @param $reason String is the log summary of the move, used for spam checking
 3007+ * @return Mixed True on success, getUserPermissionsErrors()-like array on failure
29983008 */
29993009 public function isValidMoveOperation( &$nt, $auth = true, $reason = '' ) {
30003010 global $wgUser;
@@ -3025,28 +3035,13 @@
30263036 }
30273037 if ( ( $this->getDBkey() == '' ) ||
30283038 ( !$oldid ) ||
3029 - ( $nt->getDBkey() == '' ) ) {
 3039+ ( $nt->getDBkey() == '' ) ) {
30303040 $errors[] = array( 'badarticleerror' );
30313041 }
30323042
30333043 // Image-specific checks
30343044 if ( $this->getNamespace() == NS_FILE ) {
3035 - if ( $nt->getNamespace() != NS_FILE ) {
3036 - $errors[] = array( 'imagenocrossnamespace' );
3037 - }
3038 - $file = wfLocalFile( $this );
3039 - if ( $file->exists() ) {
3040 - if ( $nt->getText() != wfStripIllegalFilenameChars( $nt->getText() ) ) {
3041 - $errors[] = array( 'imageinvalidfilename' );
3042 - }
3043 - if ( !File::checkExtensionCompatibility( $file, $nt->getDBkey() ) ) {
3044 - $errors[] = array( 'imagetypemismatch' );
3045 - }
3046 - }
3047 - $destfile = wfLocalFile( $nt );
3048 - if ( !$wgUser->isAllowed( 'reupload-shared' ) && !$destfile->exists() && wfFindFile( $nt ) ) {
3049 - $errors[] = array( 'file-exists-sharedrepo' );
3050 - }
 3045+ $errors = array_merge( $errors, $this->validateFileMoveOperation( $nt ) );
30513046 }
30523047
30533048 if ( $nt->getNamespace() == NS_FILE && $this->getNamespace() != NS_FILE ) {
@@ -3094,25 +3089,56 @@
30953090 }
30963091
30973092 /**
 3093+ * Check if the requested move target is a valid file move target
 3094+ * @param Title $nt Target title
 3095+ * @return array List of errors
 3096+ */
 3097+ protected function validateFileMoveOperation( $nt ) {
 3098+ global $wgUser;
 3099+
 3100+ $errors = array();
 3101+
 3102+ if ( $nt->getNamespace() != NS_FILE ) {
 3103+ $errors[] = array( 'imagenocrossnamespace' );
 3104+ }
 3105+
 3106+ $file = wfLocalFile( $this );
 3107+ if ( $file->exists() ) {
 3108+ if ( $nt->getText() != wfStripIllegalFilenameChars( $nt->getText() ) ) {
 3109+ $errors[] = array( 'imageinvalidfilename' );
 3110+ }
 3111+ if ( !File::checkExtensionCompatibility( $file, $nt->getDBkey() ) ) {
 3112+ $errors[] = array( 'imagetypemismatch' );
 3113+ }
 3114+ }
 3115+
 3116+ $destFile = wfLocalFile( $nt );
 3117+ if ( !$wgUser->isAllowed( 'reupload-shared' ) && !$destFile->exists() && wfFindFile( $nt ) ) {
 3118+ $errors[] = array( 'file-exists-sharedrepo' );
 3119+ }
 3120+
 3121+ return $errors;
 3122+ }
 3123+
 3124+ /**
30983125 * Move a title to a new location
30993126 *
3100 - * @param $nt \type{Title} the new title
3101 - * @param $auth \type{\bool} indicates whether $wgUser's permissions
 3127+ * @param $nt Title the new title
 3128+ * @param $auth Bool indicates whether $wgUser's permissions
31023129 * should be checked
3103 - * @param $reason \type{\string} The reason for the move
3104 - * @param $createRedirect \type{\bool} Whether to create a redirect from the old title to the new title.
 3130+ * @param $reason String the reason for the move
 3131+ * @param $createRedirect Bool Whether to create a redirect from the old title to the new title.
31053132 * Ignored if the user doesn't have the suppressredirect right.
3106 - * @return \type{\mixed} true on success, getUserPermissionsErrors()-like array on failure
 3133+ * @return Mixed true on success, getUserPermissionsErrors()-like array on failure
31073134 */
31083135 public function moveTo( &$nt, $auth = true, $reason = '', $createRedirect = true ) {
3109 - global $wgContLang, $wgEnableInterwikiTemplatesTracking, $wgGlobalDatabase;
3110 -
31113136 $err = $this->isValidMoveOperation( $nt, $auth, $reason );
31123137 if ( is_array( $err ) ) {
31133138 return $err;
31143139 }
31153140
3116 - // If it is a file, move it first. It is done before all other moving stuff is done because it's hard to revert
 3141+ // If it is a file, move it first. It is done before all other moving stuff is
 3142+ // done because it's hard to revert
31173143 $dbw = wfGetDB( DB_MASTER );
31183144 if ( $this->getNamespace() == NS_FILE ) {
31193145 $file = wfLocalFile( $this );
@@ -3127,43 +3153,39 @@
31283154 $dbw->begin(); # If $file was a LocalFile, its transaction would have closed our own.
31293155 $pageid = $this->getArticleID( self::GAID_FOR_UPDATE );
31303156 $protected = $this->isProtected();
3131 - if ( $nt->exists() ) {
3132 - $err = $this->moveOverExistingRedirect( $nt, $reason, $createRedirect );
3133 - $pageCountChange = ( $createRedirect ? 0 : -1 );
3134 - } else { # Target didn't exist, do normal move.
3135 - $err = $this->moveToNewTitle( $nt, $reason, $createRedirect );
3136 - $pageCountChange = ( $createRedirect ? 1 : 0 );
3137 - }
 3157+ $pageCountChange = ( $createRedirect ? 1 : 0 ) - ( $nt->exists() ? 1 : 0 );
31383158
 3159+ // Do the actual move
 3160+ $err = $this->moveToInternal( $nt, $reason, $createRedirect );
31393161 if ( is_array( $err ) ) {
31403162 # @todo FIXME: What about the File we have already moved?
31413163 $dbw->rollback();
31423164 return $err;
31433165 }
 3166+
31443167 $redirid = $this->getArticleID();
31453168
31463169 // Refresh the sortkey for this row. Be careful to avoid resetting
31473170 // cl_timestamp, which may disturb time-based lists on some sites.
3148 - $prefix = $dbw->selectField(
 3171+ $prefixes = $dbw->select(
31493172 'categorylinks',
3150 - 'cl_sortkey_prefix',
 3173+ array( 'cl_sortkey_prefix', 'cl_to' ),
31513174 array( 'cl_from' => $pageid ),
31523175 __METHOD__
31533176 );
3154 - $dbw->update( 'categorylinks',
3155 - array(
3156 - 'cl_sortkey' => $wgContLang->convertToSortkey( $nt->getCategorySortkey( $prefix ) ),
3157 - 'cl_timestamp=cl_timestamp' ),
3158 - array( 'cl_from' => $pageid ),
3159 - __METHOD__ );
3160 -
3161 - if ( $wgEnableInterwikiTemplatesTracking && $wgGlobalDatabase ) {
3162 - $dbw2 = wfGetDB( DB_MASTER, array(), $wgGlobalDatabase );
3163 - $dbw2->update( 'globaltemplatelinks',
3164 - array( 'gtl_from_namespace' => $nt->getNsText(),
3165 - 'gtl_from_title' => $nt->getText() ),
3166 - array ( 'gtl_from_page' => $pageid ),
3167 - __METHOD__ );
 3177+ foreach ( $prefixes as $prefixRow ) {
 3178+ $prefix = $prefixRow->cl_sortkey_prefix;
 3179+ $catTo = $prefixRow->cl_to;
 3180+ $dbw->update( 'categorylinks',
 3181+ array(
 3182+ 'cl_sortkey' => Collation::singleton()->getSortKey(
 3183+ $nt->getCategorySortkey( $prefix ) ),
 3184+ 'cl_timestamp=cl_timestamp' ),
 3185+ array(
 3186+ 'cl_from' => $pageid,
 3187+ 'cl_to' => $catTo ),
 3188+ __METHOD__
 3189+ );
31683190 }
31693191
31703192 if ( $protected ) {
@@ -3229,20 +3251,19 @@
32303252 $u->doUpdate();
32313253 }
32323254 # Update message cache for interface messages
3233 - if ( $nt->getNamespace() == NS_MEDIAWIKI ) {
3234 - global $wgMessageCache;
3235 -
 3255+ if ( $this->getNamespace() == NS_MEDIAWIKI ) {
32363256 # @bug 17860: old article can be deleted, if this the case,
32373257 # delete it from message cache
32383258 if ( $this->getArticleID() === 0 ) {
3239 - $wgMessageCache->replace( $this->getDBkey(), false );
 3259+ MessageCache::singleton()->replace( $this->getDBkey(), false );
32403260 } else {
32413261 $oldarticle = new Article( $this );
3242 - $wgMessageCache->replace( $this->getDBkey(), $oldarticle->getContent() );
 3262+ MessageCache::singleton()->replace( $this->getDBkey(), $oldarticle->getContent() );
32433263 }
3244 -
 3264+ }
 3265+ if ( $nt->getNamespace() == NS_MEDIAWIKI ) {
32453266 $newarticle = new Article( $nt );
3246 - $wgMessageCache->replace( $nt->getDBkey(), $newarticle->getContent() );
 3267+ MessageCache::singleton()->replace( $nt->getDBkey(), $newarticle->getContent() );
32473268 }
32483269
32493270 global $wgUser;
@@ -3251,78 +3272,80 @@
32523273 }
32533274
32543275 /**
3255 - * Move page to a title which is at present a redirect to the
3256 - * source page
 3276+ * Move page to a title which is either a redirect to the
 3277+ * source page or nonexistent
32573278 *
3258 - * @param $nt \type{Title} the page to move to, which should currently
3259 - * be a redirect
3260 - * @param $reason \type{\string} The reason for the move
3261 - * @param $createRedirect \type{\bool} Whether to leave a redirect at the old title.
3262 - * Ignored if the user doesn't have the suppressredirect right
 3279+ * @param $nt Title the page to move to, which should be a redirect or nonexistent
 3280+ * @param $reason String The reason for the move
 3281+ * @param $createRedirect Bool Whether to leave a redirect at the old title. Ignored
 3282+ * if the user doesn't have the suppressredirect right
32633283 */
3264 - private function moveOverExistingRedirect( &$nt, $reason = '', $createRedirect = true ) {
3265 - global $wgUseSquid, $wgUser, $wgContLang, $wgEnableInterwikiTemplatesTracking, $wgGlobalDatabase;
 3284+ private function moveToInternal( &$nt, $reason = '', $createRedirect = true ) {
 3285+ global $wgUser, $wgContLang;
32663286
3267 - $comment = wfMsgForContent( '1movedto2_redir', $this->getPrefixedText(), $nt->getPrefixedText() );
 3287+ $moveOverRedirect = $nt->exists();
32683288
 3289+ $commentMsg = ( $moveOverRedirect ? '1movedto2_redir' : '1movedto2' );
 3290+ $comment = wfMsgForContent( $commentMsg, $this->getPrefixedText(), $nt->getPrefixedText() );
 3291+
32693292 if ( $reason ) {
32703293 $comment .= wfMsgForContent( 'colon-separator' ) . $reason;
32713294 }
3272 - # Truncate for whole multibyte characters. +5 bytes for ellipsis
3273 - $comment = $wgContLang->truncate( $comment, 250 );
 3295+ # Truncate for whole multibyte characters.
 3296+ $comment = $wgContLang->truncate( $comment, 255 );
32743297
3275 - $now = wfTimestampNow();
3276 - $newid = $nt->getArticleID();
32773298 $oldid = $this->getArticleID();
32783299 $latest = $this->getLatestRevID();
32793300
 3301+ $oldns = $this->getNamespace();
 3302+ $olddbk = $this->getDBkey();
 3303+
32803304 $dbw = wfGetDB( DB_MASTER );
32813305
3282 - $rcts = $dbw->timestamp( $nt->getEarliestRevTime() );
3283 - $newns = $nt->getNamespace();
3284 - $newdbk = $nt->getDBkey();
 3306+ if ( $moveOverRedirect ) {
 3307+ $rcts = $dbw->timestamp( $nt->getEarliestRevTime() );
32853308
3286 - # Delete the old redirect. We don't save it to history since
3287 - # by definition if we've got here it's rather uninteresting.
3288 - # We have to remove it so that the next step doesn't trigger
3289 - # a conflict on the unique namespace+title index...
3290 - $dbw->delete( 'page', array( 'page_id' => $newid ), __METHOD__ );
3291 - if ( !$dbw->cascadingDeletes() ) {
3292 - $dbw->delete( 'revision', array( 'rev_page' => $newid ), __METHOD__ );
3293 - global $wgUseTrackbacks;
3294 - if ( $wgUseTrackbacks ) {
3295 - $dbw->delete( 'trackbacks', array( 'tb_page' => $newid ), __METHOD__ );
 3309+ $newid = $nt->getArticleID();
 3310+ $newns = $nt->getNamespace();
 3311+ $newdbk = $nt->getDBkey();
 3312+
 3313+ # Delete the old redirect. We don't save it to history since
 3314+ # by definition if we've got here it's rather uninteresting.
 3315+ # We have to remove it so that the next step doesn't trigger
 3316+ # a conflict on the unique namespace+title index...
 3317+ $dbw->delete( 'page', array( 'page_id' => $newid ), __METHOD__ );
 3318+ if ( !$dbw->cascadingDeletes() ) {
 3319+ $dbw->delete( 'revision', array( 'rev_page' => $newid ), __METHOD__ );
 3320+ global $wgUseTrackbacks;
 3321+ if ( $wgUseTrackbacks ) {
 3322+ $dbw->delete( 'trackbacks', array( 'tb_page' => $newid ), __METHOD__ );
 3323+ }
 3324+ $dbw->delete( 'pagelinks', array( 'pl_from' => $newid ), __METHOD__ );
 3325+ $dbw->delete( 'imagelinks', array( 'il_from' => $newid ), __METHOD__ );
 3326+ $dbw->delete( 'categorylinks', array( 'cl_from' => $newid ), __METHOD__ );
 3327+ $dbw->delete( 'templatelinks', array( 'tl_from' => $newid ), __METHOD__ );
 3328+ $dbw->delete( 'externallinks', array( 'el_from' => $newid ), __METHOD__ );
 3329+ $dbw->delete( 'langlinks', array( 'll_from' => $newid ), __METHOD__ );
 3330+ $dbw->delete( 'redirect', array( 'rd_from' => $newid ), __METHOD__ );
32963331 }
3297 - $dbw->delete( 'pagelinks', array( 'pl_from' => $newid ), __METHOD__ );
3298 - $dbw->delete( 'imagelinks', array( 'il_from' => $newid ), __METHOD__ );
3299 - $dbw->delete( 'categorylinks', array( 'cl_from' => $newid ), __METHOD__ );
3300 - $dbw->delete( 'templatelinks', array( 'tl_from' => $newid ), __METHOD__ );
3301 - $dbw->delete( 'externallinks', array( 'el_from' => $newid ), __METHOD__ );
3302 - $dbw->delete( 'langlinks', array( 'll_from' => $newid ), __METHOD__ );
3303 - $dbw->delete( 'redirect', array( 'rd_from' => $newid ), __METHOD__ );
3304 -
3305 - if ( $wgEnableInterwikiTemplatesTracking && $wgGlobalDatabase ) {
3306 - $dbw2 = wfGetDB( DB_MASTER, array(), $wgGlobalDatabase );
3307 - $dbw2->delete( 'globaltemplatelinks',
3308 - array( 'gtl_from_wiki' => wfWikiID( ),
3309 - 'gtl_from_page' => $newid ),
3310 - __METHOD__ );
3311 - }
 3332+ // If the target page was recently created, it may have an entry in recentchanges still
 3333+ $dbw->delete( 'recentchanges',
 3334+ array( 'rc_timestamp' => $rcts, 'rc_namespace' => $newns, 'rc_title' => $newdbk, 'rc_new' => 1 ),
 3335+ __METHOD__
 3336+ );
33123337 }
3313 - // If the redirect was recently created, it may have an entry in recentchanges still
3314 - $dbw->delete( 'recentchanges',
3315 - array( 'rc_timestamp' => $rcts, 'rc_namespace' => $newns, 'rc_title' => $newdbk, 'rc_new' => 1 ),
3316 - __METHOD__
3317 - );
33183338
33193339 # Save a null revision in the page's history notifying of the move
33203340 $nullRevision = Revision::newNullRevision( $dbw, $oldid, $comment, true );
 3341+ if ( !is_object( $nullRevision ) ) {
 3342+ throw new MWException( 'No valid null revision produced in ' . __METHOD__ );
 3343+ }
33213344 $nullRevId = $nullRevision->insertOn( $dbw );
33223345
33233346 # Change the name of the target page:
33243347 $dbw->update( 'page',
33253348 /* SET */ array(
3326 - 'page_touched' => $dbw->timestamp( $now ),
 3349+ 'page_touched' => $dbw->timestamp(),
33273350 'page_namespace' => $nt->getNamespace(),
33283351 'page_title' => $nt->getDBkey(),
33293352 'page_latest' => $nullRevId,
@@ -3361,110 +3384,34 @@
33623385 __METHOD__ );
33633386 $redirectSuppressed = false;
33643387 } else {
 3388+ // Get rid of old new page entries in Special:NewPages and RC.
 3389+ // Needs to be before $this->resetArticleID( 0 ).
 3390+ $dbw->delete( 'recentchanges', array(
 3391+ 'rc_timestamp' => $dbw->timestamp( $this->getEarliestRevTime() ),
 3392+ 'rc_namespace' => $oldns,
 3393+ 'rc_title' => $olddbk,
 3394+ 'rc_new' => 1
 3395+ ),
 3396+ __METHOD__
 3397+ );
 3398+
33653399 $this->resetArticleID( 0 );
33663400 $redirectSuppressed = true;
33673401 }
33683402
33693403 # Log the move
33703404 $log = new LogPage( 'move' );
3371 - $log->addEntry( 'move_redir', $this, $reason, array( 1 => $nt->getPrefixedText(), 2 => $redirectSuppressed ) );
 3405+ $logType = ( $moveOverRedirect ? 'move_redir' : 'move' );
 3406+ $log->addEntry( $logType, $this, $reason, array( 1 => $nt->getPrefixedText(), 2 => $redirectSuppressed ) );
33723407
3373 - # Purge squid
3374 - if ( $wgUseSquid ) {
3375 - $urls = array_merge( $nt->getSquidURLs(), $this->getSquidURLs() );
3376 - $u = new SquidUpdate( $urls );
3377 - $u->doUpdate();
3378 - }
3379 -
3380 - }
3381 -
3382 - /**
3383 - * Move page to non-existing title.
3384 - *
3385 - * @param $nt \type{Title} the new Title
3386 - * @param $reason \type{\string} The reason for the move
3387 - * @param $createRedirect \type{\bool} Whether to create a redirect from the old title to the new title
3388 - * Ignored if the user doesn't have the suppressredirect right
3389 - */
3390 - private function moveToNewTitle( &$nt, $reason = '', $createRedirect = true ) {
3391 - global $wgUser, $wgContLang;
3392 -
3393 - $comment = wfMsgForContent( '1movedto2', $this->getPrefixedText(), $nt->getPrefixedText() );
3394 - if ( $reason ) {
3395 - $comment .= wfMsgExt( 'colon-separator',
3396 - array( 'escapenoentities', 'content' ) );
3397 - $comment .= $reason;
3398 - }
3399 - # Truncate for whole multibyte characters. +5 bytes for ellipsis
3400 - $comment = $wgContLang->truncate( $comment, 250 );
3401 -
3402 - $newid = $nt->getArticleID();
3403 - $oldid = $this->getArticleID();
3404 - $latest = $this->getLatestRevId();
3405 -
3406 - $dbw = wfGetDB( DB_MASTER );
3407 - $now = $dbw->timestamp();
3408 -
3409 - # Save a null revision in the page's history notifying of the move
3410 - $nullRevision = Revision::newNullRevision( $dbw, $oldid, $comment, true );
3411 - if ( !is_object( $nullRevision ) ) {
3412 - throw new MWException( 'No valid null revision produced in ' . __METHOD__ );
3413 - }
3414 - $nullRevId = $nullRevision->insertOn( $dbw );
3415 -
3416 - $article = new Article( $this );
3417 - wfRunHooks( 'NewRevisionFromEditComplete', array( $article, $nullRevision, $latest, $wgUser ) );
3418 -
3419 - # Rename page entry
3420 - $dbw->update( 'page',
3421 - /* SET */ array(
3422 - 'page_touched' => $now,
3423 - 'page_namespace' => $nt->getNamespace(),
3424 - 'page_title' => $nt->getDBkey(),
3425 - 'page_latest' => $nullRevId,
3426 - ),
3427 - /* WHERE */ array( 'page_id' => $oldid ),
3428 - __METHOD__
3429 - );
3430 - $nt->resetArticleID( $oldid );
3431 -
3432 - if ( $createRedirect || !$wgUser->isAllowed( 'suppressredirect' ) ) {
3433 - # Insert redirect
3434 - $mwRedir = MagicWord::get( 'redirect' );
3435 - $redirectText = $mwRedir->getSynonym( 0 ) . ' [[' . $nt->getPrefixedText() . "]]\n";
3436 - $redirectArticle = new Article( $this );
3437 - $newid = $redirectArticle->insertOn( $dbw );
3438 - $redirectRevision = new Revision( array(
3439 - 'page' => $newid,
3440 - 'comment' => $comment,
3441 - 'text' => $redirectText ) );
3442 - $redirectRevision->insertOn( $dbw );
3443 - $redirectArticle->updateRevisionOn( $dbw, $redirectRevision, 0 );
3444 -
3445 - wfRunHooks( 'NewRevisionFromEditComplete', array( $redirectArticle, $redirectRevision, false, $wgUser ) );
3446 -
3447 - # Record the just-created redirect's linking to the page
3448 - $dbw->insert( 'pagelinks',
3449 - array(
3450 - 'pl_from' => $newid,
3451 - 'pl_namespace' => $nt->getNamespace(),
3452 - 'pl_title' => $nt->getDBkey() ),
3453 - __METHOD__ );
3454 - $redirectSuppressed = false;
 3408+ # Purge caches for old and new titles
 3409+ if ( $moveOverRedirect ) {
 3410+ # A simple purge is enough when moving over a redirect
 3411+ $nt->purgeSquid();
34553412 } else {
3456 - $this->resetArticleID( 0 );
3457 - $redirectSuppressed = true;
 3413+ # Purge caches as per article creation, including any pages that link to this title
 3414+ Article::onArticleCreate( $nt );
34583415 }
3459 -
3460 - # Log the move
3461 - $log = new LogPage( 'move' );
3462 - $log->addEntry( 'move', $this, $reason, array( 1 => $nt->getPrefixedText(), 2 => $redirectSuppressed ) );
3463 -
3464 - # Purge caches as per article creation
3465 - Article::onArticleCreate( $nt );
3466 -
3467 - # Purge old title from squid
3468 - # The new title, and links to the new title, are purged in Article::onArticleCreate()
34693416 $this->purgeSquid();
34703417 }
34713418
@@ -3474,10 +3421,11 @@
34753422 * @param $nt Title Move target
34763423 * @param $auth bool Whether $wgUser's permissions should be checked
34773424 * @param $reason string The reason for the move
3478 - * @param $createRedirect bool Whether to create redirects from the old subpages to the new ones
3479 - * Ignored if the user doesn't have the 'suppressredirect' right
 3425+ * @param $createRedirect bool Whether to create redirects from the old subpages to
 3426+ * the new ones Ignored if the user doesn't have the 'suppressredirect' right
34803427 * @return mixed array with old page titles as keys, and strings (new page titles) or
3481 - * arrays (errors) as values, or an error array with numeric indices if no pages were moved
 3428+ * arrays (errors) as values, or an error array with numeric indices if no pages
 3429+ * were moved
34823430 */
34833431 public function moveSubpages( $nt, $auth = true, $reason = '', $createRedirect = true ) {
34843432 global $wgMaximumMovedPages;
@@ -3544,7 +3492,7 @@
35453493 * Checks if this page is just a one-rev redirect.
35463494 * Adds lock, so don't use just for light purposes.
35473495 *
3548 - * @return \type{\bool}
 3496+ * @return Bool
35493497 */
35503498 public function isSingleRevRedirect() {
35513499 $dbw = wfGetDB( DB_MASTER );
@@ -3581,8 +3529,8 @@
35823530 * Checks if $this can be moved to a given Title
35833531 * - Selects for update, so don't call it unless you mean business
35843532 *
3585 - * @param $nt \type{Title} the new title to check
3586 - * @return \type{\bool} TRUE or FALSE
 3533+ * @param $nt Title the new title to check
 3534+ * @return Bool
35873535 */
35883536 public function isValidMoveTarget( $nt ) {
35893537 # Is it an existing file?
@@ -3623,7 +3571,7 @@
36243572 /**
36253573 * Can this title be added to a user's watchlist?
36263574 *
3627 - * @return \type{\bool} TRUE or FALSE
 3575+ * @return Bool TRUE or FALSE
36283576 */
36293577 public function isWatchable() {
36303578 return !$this->isExternal() && MWNamespace::isWatchable( $this->getNamespace() );
@@ -3633,31 +3581,35 @@
36343582 * Get categories to which this Title belongs and return an array of
36353583 * categories' names.
36363584 *
3637 - * @return \type{\array} array an array of parents in the form:
3638 - * $parent => $currentarticle
 3585+ * @return Array of parents in the form:
 3586+ * $parent => $currentarticle
36393587 */
36403588 public function getParentCategories() {
36413589 global $wgContLang;
36423590
3643 - $titlekey = $this->getArticleId();
 3591+ $data = array();
 3592+
 3593+ $titleKey = $this->getArticleId();
 3594+
 3595+ if ( $titleKey === 0 ) {
 3596+ return $data;
 3597+ }
 3598+
36443599 $dbr = wfGetDB( DB_SLAVE );
3645 - $categorylinks = $dbr->tableName( 'categorylinks' );
36463600
3647 - # NEW SQL
3648 - $sql = "SELECT * FROM $categorylinks"
3649 - . " WHERE cl_from='$titlekey'"
3650 - . " AND cl_from <> '0'"
3651 - . " ORDER BY cl_sortkey";
 3601+ $res = $dbr->select( 'categorylinks', '*',
 3602+ array(
 3603+ 'cl_from' => $titleKey,
 3604+ ),
 3605+ __METHOD__,
 3606+ array()
 3607+ );
36523608
3653 - $res = $dbr->query( $sql );
3654 -
36553609 if ( $dbr->numRows( $res ) > 0 ) {
3656 - foreach ( $res as $row )
 3610+ foreach ( $res as $row ) {
36573611 // $data[] = Title::newFromText($wgContLang->getNSText ( NS_CATEGORY ).':'.$row->cl_to);
36583612 $data[$wgContLang->getNSText( NS_CATEGORY ) . ':' . $row->cl_to] = $this->getFullText();
3659 - $dbr->freeResult( $res );
3660 - } else {
3661 - $data = array();
 3613+ }
36623614 }
36633615 return $data;
36643616 }
@@ -3665,8 +3617,8 @@
36663618 /**
36673619 * Get a tree of parent categories
36683620 *
3669 - * @param $children \type{\array} an array with the children in the keys, to check for circular refs
3670 - * @return \type{\array} Tree of parent categories
 3621+ * @param $children Array with the children in the keys, to check for circular refs
 3622+ * @return Array Tree of parent categories
36713623 */
36723624 public function getParentCategoryTree( $children = array() ) {
36733625 $stack = array();
@@ -3684,18 +3636,16 @@
36853637 }
36863638 }
36873639 }
3688 - return $stack;
3689 - } else {
3690 - return array();
36913640 }
 3641+
 3642+ return $stack;
36923643 }
36933644
3694 -
36953645 /**
36963646 * Get an associative array for selecting this title from
36973647 * the "page" table
36983648 *
3699 - * @return \type{\array} Selection array
 3649+ * @return Array suitable for the $where parameter of DB::select()
37003650 */
37013651 public function pageCond() {
37023652 if ( $this->mArticleID > 0 ) {
@@ -3709,12 +3659,12 @@
37103660 /**
37113661 * Get the revision ID of the previous revision
37123662 *
3713 - * @param $revId \type{\int} Revision ID. Get the revision that was before this one.
3714 - * @param $flags \type{\int} GAID_FOR_UPDATE
3715 - * @return \twotypes{\int,\bool} Old revision ID, or FALSE if none exists
 3663+ * @param $revId Int Revision ID. Get the revision that was before this one.
 3664+ * @param $flags Int Title::GAID_FOR_UPDATE
 3665+ * @return Int|Bool Old revision ID, or FALSE if none exists
37163666 */
37173667 public function getPreviousRevisionID( $revId, $flags = 0 ) {
3718 - $db = ( $flags & GAID_FOR_UPDATE ) ? wfGetDB( DB_MASTER ) : wfGetDB( DB_SLAVE );
 3668+ $db = ( $flags & self::GAID_FOR_UPDATE ) ? wfGetDB( DB_MASTER ) : wfGetDB( DB_SLAVE );
37193669 return $db->selectField( 'revision', 'rev_id',
37203670 array(
37213671 'rev_page' => $this->getArticleId( $flags ),
@@ -3728,12 +3678,12 @@
37293679 /**
37303680 * Get the revision ID of the next revision
37313681 *
3732 - * @param $revId \type{\int} Revision ID. Get the revision that was after this one.
3733 - * @param $flags \type{\int} GAID_FOR_UPDATE
3734 - * @return \twotypes{\int,\bool} Next revision ID, or FALSE if none exists
 3682+ * @param $revId Int Revision ID. Get the revision that was after this one.
 3683+ * @param $flags Int Title::GAID_FOR_UPDATE
 3684+ * @return Int|Bool Next revision ID, or FALSE if none exists
37353685 */
37363686 public function getNextRevisionID( $revId, $flags = 0 ) {
3737 - $db = ( $flags & GAID_FOR_UPDATE ) ? wfGetDB( DB_MASTER ) : wfGetDB( DB_SLAVE );
 3687+ $db = ( $flags & self::GAID_FOR_UPDATE ) ? wfGetDB( DB_MASTER ) : wfGetDB( DB_SLAVE );
37383688 return $db->selectField( 'revision', 'rev_id',
37393689 array(
37403690 'rev_page' => $this->getArticleId( $flags ),
@@ -3747,28 +3697,37 @@
37483698 /**
37493699 * Get the first revision of the page
37503700 *
3751 - * @param $flags \type{\int} GAID_FOR_UPDATE
3752 - * @return Revision (or NULL if page doesn't exist)
 3701+ * @param $flags Int Title::GAID_FOR_UPDATE
 3702+ * @return Revision|Null if page doesn't exist
37533703 */
37543704 public function getFirstRevision( $flags = 0 ) {
3755 - $db = ( $flags & GAID_FOR_UPDATE ) ? wfGetDB( DB_MASTER ) : wfGetDB( DB_SLAVE );
37563705 $pageId = $this->getArticleId( $flags );
3757 - if ( !$pageId ) {
3758 - return null;
 3706+ if ( $pageId ) {
 3707+ $db = ( $flags & self::GAID_FOR_UPDATE ) ? wfGetDB( DB_MASTER ) : wfGetDB( DB_SLAVE );
 3708+ $row = $db->selectRow( 'revision', '*',
 3709+ array( 'rev_page' => $pageId ),
 3710+ __METHOD__,
 3711+ array( 'ORDER BY' => 'rev_timestamp ASC', 'LIMIT' => 1 )
 3712+ );
 3713+ if ( $row ) {
 3714+ return new Revision( $row );
 3715+ }
37593716 }
3760 - $row = $db->selectRow( 'revision', '*',
3761 - array( 'rev_page' => $pageId ),
3762 - __METHOD__,
3763 - array( 'ORDER BY' => 'rev_timestamp ASC', 'LIMIT' => 1 )
3764 - );
3765 - if ( !$row ) {
3766 - return null;
3767 - } else {
3768 - return new Revision( $row );
3769 - }
 3717+ return null;
37703718 }
37713719
37723720 /**
 3721+ * Get the oldest revision timestamp of this page
 3722+ *
 3723+ * @param $flags Int Title::GAID_FOR_UPDATE
 3724+ * @return String: MW timestamp
 3725+ */
 3726+ public function getEarliestRevTime( $flags = 0 ) {
 3727+ $rev = $this->getFirstRevision( $flags );
 3728+ return $rev ? $rev->getTimestamp() : null;
 3729+ }
 3730+
 3731+ /**
37733732 * Check if this is a new page
37743733 *
37753734 * @return bool
@@ -3779,45 +3738,70 @@
37803739 }
37813740
37823741 /**
3783 - * Get the oldest revision timestamp of this page
 3742+ * Get the number of revisions between the given revision.
 3743+ * Used for diffs and other things that really need it.
37843744 *
3785 - * @return String: MW timestamp
 3745+ * @param $old int|Revision Old revision or rev ID (first before range)
 3746+ * @param $new int|Revision New revision or rev ID (first after range)
 3747+ * @return Int Number of revisions between these revisions.
37863748 */
3787 - public function getEarliestRevTime() {
 3749+ public function countRevisionsBetween( $old, $new ) {
 3750+ if ( !( $old instanceof Revision ) ) {
 3751+ $old = Revision::newFromTitle( $this, (int)$old );
 3752+ }
 3753+ if ( !( $new instanceof Revision ) ) {
 3754+ $new = Revision::newFromTitle( $this, (int)$new );
 3755+ }
 3756+ if ( !$old || !$new ) {
 3757+ return 0; // nothing to compare
 3758+ }
37883759 $dbr = wfGetDB( DB_SLAVE );
3789 - if ( $this->exists() ) {
3790 - $min = $dbr->selectField( 'revision',
3791 - 'MIN(rev_timestamp)',
3792 - array( 'rev_page' => $this->getArticleId() ),
3793 - __METHOD__ );
3794 - return wfTimestampOrNull( TS_MW, $min );
3795 - }
3796 - return null;
 3760+ return (int)$dbr->selectField( 'revision', 'count(*)',
 3761+ array(
 3762+ 'rev_page' => $this->getArticleId(),
 3763+ 'rev_timestamp > ' . $dbr->addQuotes( $dbr->timestamp( $old->getTimestamp() ) ),
 3764+ 'rev_timestamp < ' . $dbr->addQuotes( $dbr->timestamp( $new->getTimestamp() ) )
 3765+ ),
 3766+ __METHOD__
 3767+ );
37973768 }
37983769
37993770 /**
3800 - * Get the number of revisions between the given revision IDs.
 3771+ * Get the number of authors between the given revision IDs.
38013772 * Used for diffs and other things that really need it.
38023773 *
3803 - * @param $old \type{\int} Revision ID.
3804 - * @param $new \type{\int} Revision ID.
3805 - * @return \type{\int} Number of revisions between these IDs.
 3774+ * @param $old int|Revision Old revision or rev ID (first before range)
 3775+ * @param $new int|Revision New revision or rev ID (first after range)
 3776+ * @param $limit Int Maximum number of authors
 3777+ * @return Int Number of revision authors between these revisions.
38063778 */
3807 - public function countRevisionsBetween( $old, $new ) {
 3779+ public function countAuthorsBetween( $old, $new, $limit ) {
 3780+ if ( !( $old instanceof Revision ) ) {
 3781+ $old = Revision::newFromTitle( $this, (int)$old );
 3782+ }
 3783+ if ( !( $new instanceof Revision ) ) {
 3784+ $new = Revision::newFromTitle( $this, (int)$new );
 3785+ }
 3786+ if ( !$old || !$new ) {
 3787+ return 0; // nothing to compare
 3788+ }
38083789 $dbr = wfGetDB( DB_SLAVE );
3809 - return (int)$dbr->selectField( 'revision', 'count(*)',
3810 - 'rev_page = ' . intval( $this->getArticleId() ) .
3811 - ' AND rev_id > ' . intval( $old ) .
3812 - ' AND rev_id < ' . intval( $new ),
3813 - __METHOD__
 3790+ $res = $dbr->select( 'revision', 'DISTINCT rev_user_text',
 3791+ array(
 3792+ 'rev_page' => $this->getArticleID(),
 3793+ 'rev_timestamp > ' . $dbr->addQuotes( $dbr->timestamp( $old->getTimestamp() ) ),
 3794+ 'rev_timestamp < ' . $dbr->addQuotes( $dbr->timestamp( $new->getTimestamp() ) )
 3795+ ), __METHOD__,
 3796+ array( 'LIMIT' => $limit + 1 ) // add one so caller knows it was truncated
38143797 );
 3798+ return (int)$dbr->numRows( $res );
38153799 }
38163800
38173801 /**
38183802 * Compare with another title.
38193803 *
3820 - * @param $title \type{Title}
3821 - * @return \type{\bool} TRUE or FALSE
 3804+ * @param $title Title
 3805+ * @return Bool
38223806 */
38233807 public function equals( Title $title ) {
38243808 // Note: === is necessary for proper matching of number-like titles.
@@ -3828,7 +3812,10 @@
38293813
38303814 /**
38313815 * Callback for usort() to do title sorts by (namespace, title)
3832 - *
 3816+ *
 3817+ * @param $a Title
 3818+ * @param $b Title
 3819+ *
38333820 * @return Integer: result of string comparison, or namespace comparison
38343821 */
38353822 public static function compare( $a, $b ) {
@@ -3842,7 +3829,7 @@
38433830 /**
38443831 * Return a string representation of this title
38453832 *
3846 - * @return \type{\string} String representation of this title
 3833+ * @return String representation of this title
38473834 */
38483835 public function __toString() {
38493836 return $this->getPrefixedText();
@@ -3855,7 +3842,7 @@
38563843 * If you want to know if a title can be meaningfully viewed, you should
38573844 * probably call the isKnown() method instead.
38583845 *
3859 - * @return \type{\bool}
 3846+ * @return Bool
38603847 */
38613848 public function exists() {
38623849 return $this->getArticleId() != 0;
@@ -3875,28 +3862,28 @@
38763863 * existing code, but we might want to add an optional parameter to skip
38773864 * it and any other expensive checks.)
38783865 *
3879 - * @return \type{\bool}
 3866+ * @return Bool
38803867 */
38813868 public function isAlwaysKnown() {
38823869 if ( $this->mInterwiki != '' ) {
38833870 return true; // any interwiki link might be viewable, for all we know
38843871 }
38853872 switch( $this->mNamespace ) {
3886 - case NS_MEDIA:
3887 - case NS_FILE:
3888 - return (bool)wfFindFile( $this ); // file exists, possibly in a foreign repo
3889 - case NS_SPECIAL:
3890 - return SpecialPage::exists( $this->getDBkey() ); // valid special page
3891 - case NS_MAIN:
3892 - return $this->mDbkeyform == ''; // selflink, possibly with fragment
3893 - case NS_MEDIAWIKI:
3894 - // If the page is form Mediawiki:message/lang, calling wfMsgWeirdKey causes
3895 - // the full l10n of that language to be loaded. That takes much memory and
3896 - // isn't needed. So we strip the language part away.
3897 - list( $basename, /* rest */ ) = explode( '/', $this->mDbkeyform, 2 );
3898 - return (bool)wfMsgWeirdKey( $basename ); // known system message
3899 - default:
3900 - return false;
 3873+ case NS_MEDIA:
 3874+ case NS_FILE:
 3875+ // file exists, possibly in a foreign repo
 3876+ return (bool)wfFindFile( $this );
 3877+ case NS_SPECIAL:
 3878+ // valid special page
 3879+ return SpecialPageFactory::exists( $this->getDBkey() );
 3880+ case NS_MAIN:
 3881+ // selflink, possibly with fragment
 3882+ return $this->mDbkeyform == '';
 3883+ case NS_MEDIAWIKI:
 3884+ // known system message
 3885+ return $this->getDefaultMessageText() !== false;
 3886+ default:
 3887+ return false;
39013888 }
39023889 }
39033890
@@ -3906,10 +3893,10 @@
39073894 * links to the title should be rendered as "bluelinks" (as opposed to
39083895 * "redlinks" to non-existent pages).
39093896 *
3910 - * @return \type{\bool}
 3897+ * @return Bool
39113898 */
39123899 public function isKnown() {
3913 - return $this->exists() || $this->isAlwaysKnown();
 3900+ return $this->isAlwaysKnown() || $this->exists();
39143901 }
39153902
39163903 /**
@@ -3925,20 +3912,38 @@
39263913 if ( $this->mNamespace == NS_MEDIAWIKI ) {
39273914 // If the page doesn't exist but is a known system message, default
39283915 // message content will be displayed, same for language subpages
3929 - // Also, if the page is form Mediawiki:message/lang, calling wfMsgWeirdKey
3930 - // causes the full l10n of that language to be loaded. That takes much
3931 - // memory and isn't needed. So we strip the language part away.
3932 - list( $basename, /* rest */ ) = explode( '/', $this->mDbkeyform, 2 );
3933 - return (bool)wfMsgWeirdKey( $basename );
 3916+ return $this->getDefaultMessageText() !== false;
39343917 }
39353918
39363919 return false;
39373920 }
39383921
39393922 /**
 3923+ * Get the default message text or false if the message doesn't exist
 3924+ *
 3925+ * @return String or false
 3926+ */
 3927+ public function getDefaultMessageText() {
 3928+ global $wgContLang;
 3929+
 3930+ if ( $this->getNamespace() != NS_MEDIAWIKI ) { // Just in case
 3931+ return false;
 3932+ }
 3933+
 3934+ list( $name, $lang ) = MessageCache::singleton()->figureMessage( $wgContLang->lcfirst( $this->getText() ) );
 3935+ $message = wfMessage( $name )->inLanguage( $lang )->useDatabase( false );
 3936+
 3937+ if ( $message->exists() ) {
 3938+ return $message->plain();
 3939+ } else {
 3940+ return false;
 3941+ }
 3942+ }
 3943+
 3944+ /**
39403945 * Is this in a namespace that allows actual pages?
39413946 *
3942 - * @return \type{\bool}
 3947+ * @return Bool
39433948 * @internal note -- uses hardcoded namespace index instead of constants
39443949 */
39453950 public function canExist() {
@@ -3964,7 +3969,7 @@
39653970 * Get the last touched timestamp
39663971 *
39673972 * @param $db DatabaseBase: optional db
3968 - * @return \type{\string} Last touched timestamp
 3973+ * @return String last-touched timestamp
39693974 */
39703975 public function getTouched( $db = null ) {
39713976 $db = isset( $db ) ? $db : wfGetDB( DB_SLAVE );
@@ -3976,7 +3981,7 @@
39773982 * Get the timestamp when this page was updated since the user last saw it.
39783983 *
39793984 * @param $user User
3980 - * @return Mixed: string/null
 3985+ * @return String|Null
39813986 */
39823987 public function getNotificationTimestamp( $user = null ) {
39833988 global $wgUser, $wgShowUpdatedMarker;
@@ -3986,7 +3991,8 @@
39873992 }
39883993 // Check cache first
39893994 $uid = $user->getId();
3990 - if ( isset( $this->mNotificationTimestamp[$uid] ) ) {
 3995+ // avoid isset here, as it'll return false for null entries
 3996+ if ( array_key_exists( $uid, $this->mNotificationTimestamp ) ) {
39913997 return $this->mNotificationTimestamp[$uid];
39923998 }
39933999 if ( !$uid || !$wgShowUpdatedMarker ) {
@@ -4011,7 +4017,7 @@
40124018 /**
40134019 * Get the trackback URL for this page
40144020 *
4015 - * @return \type{\string} Trackback URL
 4021+ * @return String Trackback URL
40164022 */
40174023 public function trackbackURL() {
40184024 global $wgScriptPath, $wgServer, $wgScriptExtension;
@@ -4023,7 +4029,7 @@
40244030 /**
40254031 * Get the trackback RDF for this page
40264032 *
4027 - * @return \type{\string} Trackback RDF
 4033+ * @return String Trackback RDF
40284034 */
40294035 public function trackbackRDF() {
40304036 $url = htmlspecialchars( $this->getFullURL() );
@@ -4037,8 +4043,8 @@
40384044 // Spec: http://www.sixapart.com/pronet/docs/trackback_spec
40394045 return "<!--
40404046 <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"
4041 - xmlns:dc=\"http://purl.org/dc/elements/1.1/\"
4042 - xmlns:trackback=\"http://madskills.com/public/xml/rss/module/trackback/\">
 4047+ xmlns:dc=\"http://purl.org/dc/elements/1.1/\"
 4048+ xmlns:trackback=\"http://madskills.com/public/xml/rss/module/trackback/\">
40434049 <rdf:Description
40444050 rdf:about=\"$url\"
40454051 dc:identifier=\"$url\"
@@ -4052,7 +4058,7 @@
40534059 * Generate strings used for xml 'id' names in monobook tabs
40544060 *
40554061 * @param $prepend string defaults to 'nstab-'
4056 - * @return \type{\string} XML 'id' name
 4062+ * @return String XML 'id' name
40574063 */
40584064 public function getNamespaceKey( $prepend = 'nstab-' ) {
40594065 global $wgContLang;
@@ -4091,12 +4097,12 @@
40924098 /**
40934099 * Returns true if this title resolves to the named special page
40944100 *
4095 - * @param $name \type{\string} The special page name
 4101+ * @param $name String The special page name
40964102 * @return boolean
40974103 */
40984104 public function isSpecial( $name ) {
40994105 if ( $this->getNamespace() == NS_SPECIAL ) {
4100 - list( $thisName, /* $subpage */ ) = SpecialPage::resolveAliasWithSubpage( $this->getDBkey() );
 4106+ list( $thisName, /* $subpage */ ) = SpecialPageFactory::resolveAlias( $this->getDBkey() );
41014107 if ( $name == $thisName ) {
41024108 return true;
41034109 }
@@ -4105,16 +4111,16 @@
41064112 }
41074113
41084114 /**
4109 - * If the Title refers to a special page alias which is not the local default,
 4115+ * If the Title refers to a special page alias which is not the local default, resolve
 4116+ * the alias, and localise the name as necessary. Otherwise, return $this
41104117 *
4111 - * @return \type{Title} A new Title which points to the local default.
4112 - * Otherwise, returns $this.
 4118+ * @return Title
41134119 */
41144120 public function fixSpecialName() {
41154121 if ( $this->getNamespace() == NS_SPECIAL ) {
4116 - $canonicalName = SpecialPage::resolveAlias( $this->mDbkeyform );
 4122+ list( $canonicalName, /*...*/ ) = SpecialPageFactory::resolveAlias( $this->mDbkeyform );
41174123 if ( $canonicalName ) {
4118 - $localName = SpecialPage::getLocalNameFor( $canonicalName );
 4124+ $localName = SpecialPageFactory::getLocalNameFor( $canonicalName );
41194125 if ( $localName != $this->mDbkeyform ) {
41204126 return Title::makeTitle( NS_SPECIAL, $localName );
41214127 }
@@ -4128,7 +4134,7 @@
41294135 * In other words, is this a content page, for the purposes of calculating
41304136 * statistics, etc?
41314137 *
4132 - * @return \type{\bool}
 4138+ * @return Boolean
41334139 */
41344140 public function isContentPage() {
41354141 return MWNamespace::isContent( $this->getNamespace() );
@@ -4137,9 +4143,8 @@
41384144 /**
41394145 * Get all extant redirects to this Title
41404146 *
4141 - * @param $ns \twotypes{\int,\null} Single namespace to consider;
4142 - * NULL to consider all namespaces
4143 - * @return \type{\arrayof{Title}} Redirects to this title
 4147+ * @param $ns Int|Null Single namespace to consider; NULL to consider all namespaces
 4148+ * @return Array of Title redirects to this title
41444149 */
41454150 public function getRedirectsHere( $ns = null ) {
41464151 $redirs = array();
@@ -4161,7 +4166,6 @@
41624167 __METHOD__
41634168 );
41644169
4165 -
41664170 foreach ( $res as $row ) {
41674171 $redirs[] = self::newFromRow( $row );
41684172 }
@@ -4171,7 +4175,7 @@
41724176 /**
41734177 * Check if this Title is a valid redirect target
41744178 *
4175 - * @return \type{\bool}
 4179+ * @return Bool
41764180 */
41774181 public function isValidRedirectTarget() {
41784182 global $wgInvalidRedirectTargets;
@@ -4203,8 +4207,7 @@
42044208 }
42054209
42064210 /**
4207 - * Whether the magic words __INDEX__ and __NOINDEX__ function for
4208 - * this page.
 4211+ * Whether the magic words __INDEX__ and __NOINDEX__ function for this page.
42094212 *
42104213 * @return Boolean
42114214 */
@@ -4225,21 +4228,47 @@
42264229 * @return array applicable restriction types
42274230 */
42284231 public function getRestrictionTypes() {
4229 - global $wgRestrictionTypes;
4230 - $types = $this->exists() ? $wgRestrictionTypes : array( 'create' );
 4232+ if ( $this->getNamespace() == NS_SPECIAL ) {
 4233+ return array();
 4234+ }
42314235
4232 - if ( $this->getNamespace() == NS_FILE ) {
4233 - $types[] = 'upload';
 4236+ $types = self::getFilteredRestrictionTypes( $this->exists() );
 4237+
 4238+ if ( $this->getNamespace() != NS_FILE ) {
 4239+ # Remove the upload restriction for non-file titles
 4240+ $types = array_diff( $types, array( 'upload' ) );
42344241 }
42354242
42364243 wfRunHooks( 'TitleGetRestrictionTypes', array( $this, &$types ) );
42374244
 4245+ wfDebug( __METHOD__ . ': applicable restriction types for ' .
 4246+ $this->getPrefixedText() . ' are ' . implode( ',', $types ) . "\n" );
 4247+
42384248 return $types;
42394249 }
 4250+ /**
 4251+ * Get a filtered list of all restriction types supported by this wiki.
 4252+ * @param bool $exists True to get all restriction types that apply to
 4253+ * titles that do exist, False for all restriction types that apply to
 4254+ * titles that do not exist
 4255+ * @return array
 4256+ */
 4257+ public static function getFilteredRestrictionTypes( $exists = true ) {
 4258+ global $wgRestrictionTypes;
 4259+ $types = $wgRestrictionTypes;
 4260+ if ( $exists ) {
 4261+ # Remove the create restriction for existing titles
 4262+ $types = array_diff( $types, array( 'create' ) );
 4263+ } else {
 4264+ # Only the create and upload restrictions apply to non-existing titles
 4265+ $types = array_intersect( $types, array( 'create', 'upload' ) );
 4266+ }
 4267+ return $types;
 4268+ }
42404269
42414270 /**
42424271 * Returns the raw sort key to be used for categories, with the specified
4243 - * prefix. This will be fed to Language::convertToSortkey() to get a
 4272+ * prefix. This will be fed to Collation::getSortKey() to get a
42444273 * binary sortkey that can be used for actual sorting.
42454274 *
42464275 * @param $prefix string The prefix to be used, specified using
@@ -4256,10 +4285,12 @@
42574286 // in order to re-sort existing category relations.
42584287 wfRunHooks( 'GetDefaultSortkey', array( $this, &$unprefixed ) );
42594288 if ( $prefix !== '' ) {
4260 - # Separate with a null byte, so the unprefixed part is only used as
4261 - # a tiebreaker when two pages have the exact same prefix -- null
4262 - # sorts before everything else (hopefully).
4263 - return "$prefix\0$unprefixed";
 4289+ # Separate with a line feed, so the unprefixed part is only used as
 4290+ # a tiebreaker when two pages have the exact same prefix.
 4291+ # In UCA, tab is the only character that can sort above LF
 4292+ # so we strip both of them from the original prefix.
 4293+ $prefix = strtr( $prefix, "\n\t", ' ' );
 4294+ return "$prefix\n$unprefixed";
42644295 }
42654296 return $unprefixed;
42664297 }
@@ -4295,3 +4326,37 @@
42964327 return wfGetLangObj( $pageLang );
42974328 }
42984329 }
 4330+
 4331+/**
 4332+ * A BadTitle is generated in MediaWiki::parseTitle() if the title is invalid; the
 4333+ * software uses this to display an error page. Internally it's basically a Title
 4334+ * for an empty special page
 4335+ */
 4336+class BadTitle extends Title {
 4337+ public function __construct(){
 4338+ $this->mTextform = '';
 4339+ $this->mUrlform = '';
 4340+ $this->mDbkeyform = '';
 4341+ $this->mNamespace = NS_SPECIAL; // Stops talk page link, etc, being shown
 4342+ }
 4343+
 4344+ public function exists(){
 4345+ return false;
 4346+ }
 4347+
 4348+ public function getPrefixedText(){
 4349+ return '';
 4350+ }
 4351+
 4352+ public function getText(){
 4353+ return '';
 4354+ }
 4355+
 4356+ public function getPrefixedURL(){
 4357+ return '';
 4358+ }
 4359+
 4360+ public function getPrefixedDBKey(){
 4361+ return '';
 4362+ }
 4363+}
Property changes on: branches/iwtransclusion/phase3v3/includes/Title.php
___________________________________________________________________
Modified: svn:mergeinfo
42994364 Reverse-merged /branches/iwtransclusion/phase3v2/includes/Title.php:r87108
43004365 Reverse-merged /branches/iwtransclusion/phase3/includes/Title.php:r70764
Index: branches/iwtransclusion/phase3v3/languages/messages/MessagesEn.php
@@ -1399,9 +1399,6 @@
14001400 'templatesused' => '{{PLURAL:$1|Template|Templates}} used on this page:',
14011401 'templatesusedpreview' => '{{PLURAL:$1|Template|Templates}} used in this preview:',
14021402 'templatesusedsection' => '{{PLURAL:$1|Template|Templates}} used in this section:',
1403 -'distanttemplatesused' => 'Distant {{PLURAL:$1|template|templates}} used on this page:',
1404 -'distanttemplatesusedpreview' => 'Distant {{PLURAL:$1|template|templates}} used in this preview:',
1405 -'distanttemplatesusedsection' => 'Distant {{PLURAL:$1|template|templates}} used in this section:',
14061403 'template-protected' => '(protected)',
14071404 'template-semiprotected' => '(semi-protected)',
14081405 'hiddencategories' => 'This page is a member of {{PLURAL:$1|1 hidden category|$1 hidden categories}}:',

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r92990Merge r87108, Merge r70764reedy17:38, 24 July 2011

Status & tagging log