Index: branches/iwtransclusion/phase3v3/maintenance/archives/patch-globaltemplatelinks.sql |
— | — | @@ -17,19 +17,15 @@ |
18 | 18 | -- Needed for display purposes |
19 | 19 | gtl_from_title varchar(255) binary NOT NULL, |
20 | 20 | |
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, |
23 | 23 | |
24 | 24 | -- The namespace of the transcluded page on that wiki |
25 | 25 | gtl_to_namespace int NOT NULL, |
26 | 26 | |
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 | | - |
31 | 27 | -- The title of the transcluded page on that wiki |
32 | 28 | gtl_to_title varchar(255) binary NOT NULL |
33 | 29 | ) /*$wgDBTableOptions*/; |
34 | 30 | |
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 @@ |
640 | 640 | 'templatesused', |
641 | 641 | 'templatesusedpreview', |
642 | 642 | 'templatesusedsection', |
643 | | - 'distanttemplatesused', |
644 | | - 'distanttemplatesusedpreview', |
645 | | - 'distanttemplatesusedsection', |
646 | 643 | 'template-protected', |
647 | 644 | 'template-semiprotected', |
648 | 645 | 'hiddencategories', |
Index: branches/iwtransclusion/phase3v3/includes/Article.php |
— | — | @@ -1627,594 +1627,6 @@ |
1628 | 1628 | } |
1629 | 1629 | |
1630 | 1630 | /** |
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 | | - /** |
2219 | 1631 | * Generate the navigation links when browsing through an article revisions |
2220 | 1632 | * It shows the information as: |
2221 | 1633 | * Revision as of \<date\>; view current revision |
— | — | @@ -2482,166 +1894,6 @@ |
2483 | 1895 | } |
2484 | 1896 | |
2485 | 1897 | /** |
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 | | - /** |
2646 | 1898 | * This does all the heavy lifting for outputWikitext, except it returns the parser |
2647 | 1899 | * output instead of sending it straight to $wgOut. Makes things nice and simple for, |
2648 | 1900 | * say, embedding thread pages within a discussion system (LiquidThreads) |
Index: branches/iwtransclusion/phase3v3/includes/parser/Parser.php |
— | — | @@ -3051,7 +3051,7 @@ |
3052 | 3052 | * @private |
3053 | 3053 | */ |
3054 | 3054 | function braceSubstitution( $piece, $frame ) { |
3055 | | - global $wgContLang, $wgNonincludableNamespaces, $wgEnableInterwikiTranscluding, $wgEnableInterwikiTemplatesTracking; |
| 3055 | + global $wgContLang, $wgNonincludableNamespaces; |
3056 | 3056 | wfProfileIn( __METHOD__ ); |
3057 | 3057 | wfProfileIn( __METHOD__.'-setup' ); |
3058 | 3058 | |
— | — | @@ -3266,15 +3266,11 @@ |
3267 | 3267 | $text = "[[:$titleText]]"; |
3268 | 3268 | $found = true; |
3269 | 3269 | } |
3270 | | - } elseif ( $wgEnableInterwikiTranscluding && $title->isTrans() ) { |
| 3270 | + } elseif ( $title->isTrans() ) { |
3271 | 3271 | // TODO: Work by Peter17 in progress |
3272 | 3272 | |
3273 | 3273 | $text = Interwiki::interwikiTransclude( $title ); |
3274 | 3274 | |
3275 | | - if ( $wgEnableInterwikiTemplatesTracking ) { |
3276 | | - $this->registerDistantTemplate( $title ); |
3277 | | - } |
3278 | | - |
3279 | 3275 | if ( $text !== false ) { |
3280 | 3276 | # Preprocess it like a template |
3281 | 3277 | $text = $this->preprocessToDom( $text, self::PTD_FOR_INCLUSION ); |
— | — | @@ -3433,17 +3429,6 @@ |
3434 | 3430 | * @param Title $title |
3435 | 3431 | * @return mixed string or false |
3436 | 3432 | */ |
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 | | - |
3448 | 3433 | function fetchTemplate( $title ) { |
3449 | 3434 | $rv = $this->fetchTemplateAndTitle( $title ); |
3450 | 3435 | return $rv[0]; |
Index: branches/iwtransclusion/phase3v3/includes/parser/ParserOutput.php |
— | — | @@ -306,31 +306,6 @@ |
307 | 307 | $this->mTemplateIds[$ns][$dbk] = $rev_id; // For versioning |
308 | 308 | } |
309 | 309 | |
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 | | - |
335 | 310 | /** |
336 | 311 | * @param $title Title object, must be an interwiki link |
337 | 312 | * @throws MWException if given invalid input |
Index: branches/iwtransclusion/phase3v3/includes/Linker.php |
— | — | @@ -1646,48 +1646,6 @@ |
1647 | 1647 | } |
1648 | 1648 | |
1649 | 1649 | /** |
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 | | - /** |
1692 | 1650 | * Returns HTML for the "hidden categories on this page" list. |
1693 | 1651 | * |
1694 | 1652 | * @param $hiddencats Array of hidden categories from Article::getHiddenCategories |
Index: branches/iwtransclusion/phase3v3/includes/db/Database.php |
— | — | @@ -1777,31 +1777,6 @@ |
1778 | 1778 | return false; |
1779 | 1779 | } |
1780 | 1780 | } |
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 | | - } |
1806 | 1781 | |
1807 | 1782 | /** |
1808 | 1783 | * Bitwise operations |
Property changes on: branches/iwtransclusion/phase3v3/includes/db/Database.php |
___________________________________________________________________ |
Modified: svn:mergeinfo |
1809 | 1784 | Reverse-merged /branches/iwtransclusion/phase3/includes/db/Database.php:r70764 |
1810 | 1785 | Reverse-merged /branches/iwtransclusion/phase3v2/includes/db/Database.php:r87108 |
Index: branches/iwtransclusion/phase3v3/includes/EditPage.php |
— | — | @@ -1319,8 +1319,8 @@ |
1320 | 1320 | * @param $formCallback Callback that takes an OutputPage parameter; will be called |
1321 | 1321 | * during form output near the top, for captchas and the like. |
1322 | 1322 | */ |
1323 | | - function showEditForm( $formCallback=null ) { |
1324 | | - global $wgOut, $wgUser, $wgTitle, $wgEnableInterwikiTranscluding, $wgEnableInterwikiTemplatesTracking; |
| 1323 | + function showEditForm( $formCallback = null ) { |
| 1324 | + global $wgOut, $wgUser; |
1325 | 1325 | |
1326 | 1326 | wfProfileIn( __METHOD__ ); |
1327 | 1327 | |
— | — | @@ -1365,9 +1365,6 @@ |
1366 | 1366 | |
1367 | 1367 | $templates = $this->getTemplates(); |
1368 | 1368 | $formattedtemplates = Linker::formatTemplates( $templates, $this->preview, $this->section != ''); |
1369 | | - |
1370 | | - $distantTemplates = $this->getDistantTemplates(); |
1371 | | - $formattedDistantTemplates = $sk->formatDistantTemplates( $distantTemplates, $this->preview, $this->section != '' ); |
1372 | 1369 | |
1373 | 1370 | $hiddencats = $this->mArticle->getHiddenCategories(); |
1374 | 1371 | $formattedhiddencats = Linker::formatHiddenCategories( $hiddencats ); |
— | — | @@ -1467,21 +1464,6 @@ |
1468 | 1465 | <div class='templatesUsed'> |
1469 | 1466 | {$formattedtemplates} |
1470 | 1467 | </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} |
1486 | 1468 | <div class='hiddencats'> |
1487 | 1469 | {$formattedhiddencats} |
1488 | 1470 | </div> |
— | — | @@ -2137,28 +2119,6 @@ |
2138 | 2120 | return $this->mArticle->getUsedTemplates(); |
2139 | 2121 | } |
2140 | 2122 | } |
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 | | - } |
2163 | 2123 | |
2164 | 2124 | /** |
2165 | 2125 | * Call the stock "user is blocked" page |
Index: branches/iwtransclusion/phase3v3/includes/OutputPage.php |
— | — | @@ -2095,9 +2095,6 @@ |
2096 | 2096 | * @param $action String: action that was denied or null if unknown |
2097 | 2097 | */ |
2098 | 2098 | public function readOnlyPage( $source = null, $protected = false, $reasons = array(), $action = null ) { |
2099 | | - global $wgUser, $wgEnableInterwikiTranscluding, $wgEnableInterwikiTemplatesTracking; |
2100 | | - $skin = $wgUser->getSkin(); |
2101 | | - |
2102 | 2099 | $this->setRobotPolicy( 'noindex,nofollow' ); |
2103 | 2100 | $this->setArticleRelated( false ); |
2104 | 2101 | |
— | — | @@ -2143,12 +2140,6 @@ |
2144 | 2141 | $templates |
2145 | 2142 | </div> |
2146 | 2143 | " ); |
2147 | | - if ( $wgEnableInterwikiTranscluding && $wgEnableInterwikiTemplatesTracking ) { |
2148 | | - $this->addHTML( "<div class='distantTemplatesUsed'> |
2149 | | -{$skin->formatDistantTemplates( $article->getUsedDistantTemplates( ) )} |
2150 | | -</div> |
2151 | | -" ); |
2152 | | - } |
2153 | 2144 | } |
2154 | 2145 | |
2155 | 2146 | # 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 |
2156 | 2147 | Reverse-merged /branches/iwtransclusion/phase3/includes/OutputPage.php:r70764 |
2157 | 2148 | Reverse-merged /branches/iwtransclusion/phase3v2/includes/OutputPage.php:r87108 |
Index: branches/iwtransclusion/phase3v3/includes/Title.php |
— | — | @@ -21,7 +21,6 @@ |
22 | 22 | */ |
23 | 23 | |
24 | 24 | /** |
25 | | - |
26 | 25 | * Represents a title within MediaWiki. |
27 | 26 | * Optionally may contain an interwiki designation or namespace. |
28 | 27 | * @note This class can fetch various kinds of data from the database; |
— | — | @@ -42,7 +41,13 @@ |
43 | 42 | */ |
44 | 43 | const CACHE_MAX = 1000; |
45 | 44 | |
| 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; |
46 | 50 | |
| 51 | + |
47 | 52 | /** |
48 | 53 | * @name Private member variables |
49 | 54 | * Please use the accessor functions instead. |
— | — | @@ -68,11 +73,11 @@ |
69 | 74 | var $mCascadeSources; ///< Where are the cascading restrictions coming from on this page? |
70 | 75 | var $mRestrictionsLoaded = false; ///< Boolean for initialisation on demand |
71 | 76 | 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) |
73 | 78 | # Don't change the following default, NS_MAIN is hardcoded in several |
74 | 79 | # places. See bug 696. |
75 | 80 | var $mDefaultNamespace = NS_MAIN; // /< Namespace index when there is no namespace |
76 | | - # Zero except in {{transclusion}} tags |
| 81 | + # Zero except in {{transclusion}} tags |
77 | 82 | var $mWatched = null; // /< Is $wgUser watching this page? null if unfilled, accessed through userIsWatching() |
78 | 83 | var $mLength = -1; // /< The page length, 0 for special pages |
79 | 84 | var $mRedirect = null; // /< Is the article at this title a redirect? |
— | — | @@ -83,17 +88,16 @@ |
84 | 89 | |
85 | 90 | /** |
86 | 91 | * Constructor |
87 | | - * @private |
88 | 92 | */ |
89 | | - /* private */ function __construct() { } |
| 93 | + /*protected*/ function __construct() { } |
90 | 94 | |
91 | 95 | /** |
92 | 96 | * Create a new Title from a prefixed DB key |
93 | 97 | * |
94 | | - * @param $key \type{\string} The database key, which has underscores |
| 98 | + * @param $key String the database key, which has underscores |
95 | 99 | * instead of spaces, possibly including namespace and |
96 | 100 | * interwiki prefixes |
97 | | - * @return \type{Title} the new object, or NULL on an error |
| 101 | + * @return Title, or NULL on an error |
98 | 102 | */ |
99 | 103 | public static function newFromDBkey( $key ) { |
100 | 104 | $t = new Title(); |
— | — | @@ -109,13 +113,13 @@ |
110 | 114 | * Create a new Title from text, such as what one would find in a link. De- |
111 | 115 | * codes any HTML entities in the text. |
112 | 116 | * |
113 | | - * @param $text string The link text; spaces, prefixes, and an |
| 117 | + * @param $text String the link text; spaces, prefixes, and an |
114 | 118 | * 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- |
116 | 120 | * fied by a prefix. If you want to force a specific namespace even if |
117 | 121 | * $text might begin with a namespace prefix, use makeTitle() or |
118 | 122 | * makeTitleSafe(). |
119 | | - * @return Title The new object, or null on an error. |
| 123 | + * @return Title, or null on an error. |
120 | 124 | */ |
121 | 125 | public static function newFromText( $text, $defaultNamespace = NS_MAIN ) { |
122 | 126 | if ( is_object( $text ) ) { |
— | — | @@ -134,9 +138,7 @@ |
135 | 139 | return Title::$titleCache[$text]; |
136 | 140 | } |
137 | 141 | |
138 | | - /** |
139 | | - * Convert things like é ā or 〗 into normalized(bug 14952) text |
140 | | - */ |
| 142 | + # Convert things like é ā or 〗 into normalized (bug 14952) text |
141 | 143 | $filteredText = Sanitizer::decodeCharReferencesAndNormalize( $text ); |
142 | 144 | |
143 | 145 | $t = new Title(); |
— | — | @@ -173,8 +175,8 @@ |
174 | 176 | * Create a new Title from URL-encoded text. Ensures that |
175 | 177 | * the given title's length does not exceed the maximum. |
176 | 178 | * |
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 |
179 | 181 | */ |
180 | 182 | public static function newFromURL( $url ) { |
181 | 183 | global $wgLegalTitleChars; |
— | — | @@ -198,12 +200,12 @@ |
199 | 201 | /** |
200 | 202 | * Create a new Title from an article ID |
201 | 203 | * |
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 |
205 | 207 | */ |
206 | 208 | 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 ); |
208 | 210 | $row = $db->selectRow( 'page', '*', array( 'page_id' => $id ), __METHOD__ ); |
209 | 211 | if ( $row !== false ) { |
210 | 212 | $title = Title::newFromRow( $row ); |
— | — | @@ -216,15 +218,15 @@ |
217 | 219 | /** |
218 | 220 | * Make an array of titles from an array of IDs |
219 | 221 | * |
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 |
222 | 224 | */ |
223 | 225 | public static function newFromIDs( $ids ) { |
224 | 226 | if ( !count( $ids ) ) { |
225 | 227 | return array(); |
226 | 228 | } |
227 | 229 | $dbr = wfGetDB( DB_SLAVE ); |
228 | | - |
| 230 | + |
229 | 231 | $res = $dbr->select( |
230 | 232 | 'page', |
231 | 233 | array( |
— | — | @@ -245,8 +247,8 @@ |
246 | 248 | /** |
247 | 249 | * Make a Title object from a DB row |
248 | 250 | * |
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 |
251 | 253 | */ |
252 | 254 | public static function newFromRow( $row ) { |
253 | 255 | $t = self::makeTitle( $row->page_namespace, $row->page_title ); |
— | — | @@ -286,11 +288,11 @@ |
287 | 289 | * For convenience, spaces are converted to underscores so that |
288 | 290 | * eg user_text fields can be used directly. |
289 | 291 | * |
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 |
295 | 297 | */ |
296 | 298 | public static function &makeTitle( $ns, $title, $fragment = '', $interwiki = '' ) { |
297 | 299 | $t = new Title(); |
— | — | @@ -309,11 +311,11 @@ |
310 | 312 | * The parameters will be checked for validity, which is a bit slower |
311 | 313 | * than makeTitle() but safer for user-provided data. |
312 | 314 | * |
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 |
318 | 320 | */ |
319 | 321 | public static function makeTitleSafe( $ns, $title, $fragment = '', $interwiki = '' ) { |
320 | 322 | $t = new Title(); |
— | — | @@ -328,7 +330,7 @@ |
329 | 331 | /** |
330 | 332 | * Create a new Title for the Main Page |
331 | 333 | * |
332 | | - * @return \type{Title} the new object |
| 334 | + * @return Title the new object |
333 | 335 | */ |
334 | 336 | public static function newMainPage() { |
335 | 337 | $title = Title::newFromText( wfMsgForContent( 'mainpage' ) ); |
— | — | @@ -345,8 +347,8 @@ |
346 | 348 | * This will only return the very next target, useful for |
347 | 349 | * the redirect table and other checks that don't need full recursion |
348 | 350 | * |
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 |
351 | 353 | */ |
352 | 354 | public static function newFromRedirect( $text ) { |
353 | 355 | return self::newFromRedirectInternal( $text ); |
— | — | @@ -358,8 +360,8 @@ |
359 | 361 | * This will recurse down $wgMaxRedirects times or until a non-redirect target is hit |
360 | 362 | * in order to provide (hopefully) the Title of the final destination instead of another redirect |
361 | 363 | * |
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 |
364 | 366 | */ |
365 | 367 | public static function newFromRedirectRecurse( $text ) { |
366 | 368 | $titles = self::newFromRedirectArray( $text ); |
— | — | @@ -372,15 +374,11 @@ |
373 | 375 | * The last element in the array is the final destination after all redirects |
374 | 376 | * have been resolved (up to $wgMaxRedirects times) |
375 | 377 | * |
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 |
378 | 380 | */ |
379 | 381 | public static function newFromRedirectArray( $text ) { |
380 | 382 | global $wgMaxRedirects; |
381 | | - // are redirects disabled? |
382 | | - if ( $wgMaxRedirects < 1 ) { |
383 | | - return null; |
384 | | - } |
385 | 383 | $title = self::newFromRedirectInternal( $text ); |
386 | 384 | if ( is_null( $title ) ) { |
387 | 385 | return null; |
— | — | @@ -411,10 +409,15 @@ |
412 | 410 | * Really extract the redirect destination |
413 | 411 | * Do not call this function directly, use one of the newFromRedirect* functions above |
414 | 412 | * |
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 |
417 | 415 | */ |
418 | 416 | protected static function newFromRedirectInternal( $text ) { |
| 417 | + global $wgMaxRedirects; |
| 418 | + if ( $wgMaxRedirects < 1 ) { |
| 419 | + //redirects are disabled, so quit early |
| 420 | + return null; |
| 421 | + } |
419 | 422 | $redir = MagicWord::get( 'redirect' ); |
420 | 423 | $text = trim( $text ); |
421 | 424 | if ( $redir->matchStartAndRemove( $text ) ) { |
— | — | @@ -427,9 +430,7 @@ |
428 | 431 | // and URL-decode links |
429 | 432 | if ( strpos( $m[1], '%' ) !== false ) { |
430 | 433 | // 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], ':' ) ); |
434 | 435 | } |
435 | 436 | $title = Title::newFromText( $m[1] ); |
436 | 437 | // If the title is a redirect to bad special pages or is invalid, return null |
— | — | @@ -449,9 +450,8 @@ |
450 | 451 | /** |
451 | 452 | * Get the prefixed DB key associated with an ID |
452 | 453 | * |
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 |
456 | 456 | */ |
457 | 457 | public static function nameOf( $id ) { |
458 | 458 | $dbr = wfGetDB( DB_SLAVE ); |
— | — | @@ -473,7 +473,7 @@ |
474 | 474 | /** |
475 | 475 | * Get a regex character class describing the legal characters in a link |
476 | 476 | * |
477 | | - * @return \type{\string} the list of characters, not delimited |
| 477 | + * @return String the list of characters, not delimited |
478 | 478 | */ |
479 | 479 | public static function legalChars() { |
480 | 480 | global $wgLegalTitleChars; |
— | — | @@ -484,10 +484,9 @@ |
485 | 485 | * Get a string representation of a title suitable for |
486 | 486 | * including in a search index |
487 | 487 | * |
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 |
492 | 491 | */ |
493 | 492 | public static function indexTitle( $ns, $title ) { |
494 | 493 | global $wgContLang; |
— | — | @@ -512,11 +511,11 @@ |
513 | 512 | /** |
514 | 513 | * Make a prefixed DB key from a DB key and a namespace index |
515 | 514 | * |
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 |
521 | 520 | */ |
522 | 521 | public static function makeName( $ns, $title, $fragment = '', $interwiki = '' ) { |
523 | 522 | global $wgContLang; |
— | — | @@ -536,8 +535,7 @@ |
537 | 536 | * Determine whether the object refers to a page within |
538 | 537 | * this project. |
539 | 538 | * |
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 |
542 | 540 | */ |
543 | 541 | public function isLocal() { |
544 | 542 | if ( $this->mInterwiki != '' ) { |
— | — | @@ -551,7 +549,7 @@ |
552 | 550 | * Determine whether the object refers to a page within |
553 | 551 | * this project and is transcludable. |
554 | 552 | * |
555 | | - * @return \type{\bool} TRUE if this is transcludable |
| 553 | + * @return Bool TRUE if this is transcludable |
556 | 554 | */ |
557 | 555 | public function isTrans() { |
558 | 556 | if ( $this->mInterwiki == '' ) { |
— | — | @@ -560,25 +558,11 @@ |
561 | 559 | |
562 | 560 | return Interwiki::fetch( $this->mInterwiki )->isTranscludable(); |
563 | 561 | } |
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; |
574 | 562 | |
575 | | - return Interwiki::fetch( $this->mInterwiki )->getAPI(); |
576 | | - } |
577 | | - |
578 | 563 | /** |
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. |
581 | 565 | * |
582 | | - * @return \type{\string} the DB name |
| 566 | + * @return String the DB name |
583 | 567 | */ |
584 | 568 | public function getTransWikiID() { |
585 | 569 | if ( $this->mInterwiki == '' ) { |
— | — | @@ -610,35 +594,35 @@ |
611 | 595 | /** |
612 | 596 | * Get the text form (spaces not underscores) of the main part |
613 | 597 | * |
614 | | - * @return \type{\string} Main part of the title |
| 598 | + * @return String Main part of the title |
615 | 599 | */ |
616 | 600 | public function getText() { return $this->mTextform; } |
617 | 601 | |
618 | 602 | /** |
619 | 603 | * Get the URL-encoded form of the main part |
620 | 604 | * |
621 | | - * @return \type{\string} Main part of the title, URL-encoded |
| 605 | + * @return String Main part of the title, URL-encoded |
622 | 606 | */ |
623 | 607 | public function getPartialURL() { return $this->mUrlform; } |
624 | 608 | |
625 | 609 | /** |
626 | 610 | * Get the main part with underscores |
627 | 611 | * |
628 | | - * @return \type{\string} Main part of the title, with underscores |
| 612 | + * @return String: Main part of the title, with underscores |
629 | 613 | */ |
630 | 614 | public function getDBkey() { return $this->mDbkeyform; } |
631 | 615 | |
632 | 616 | /** |
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. |
634 | 618 | * |
635 | | - * @return \type{\int} Namespace index |
| 619 | + * @return Integer: Namespace index |
636 | 620 | */ |
637 | 621 | public function getNamespace() { return $this->mNamespace; } |
638 | 622 | |
639 | 623 | /** |
640 | 624 | * Get the namespace text |
641 | 625 | * |
642 | | - * @return \type{\string} Namespace text |
| 626 | + * @return String: Namespace text |
643 | 627 | */ |
644 | 628 | public function getNsText() { |
645 | 629 | global $wgContLang; |
— | — | @@ -654,13 +638,20 @@ |
655 | 639 | return MWNamespace::getCanonicalName( $this->mNamespace ); |
656 | 640 | } |
657 | 641 | } |
| 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 | + |
658 | 649 | return $wgContLang->getNsText( $this->mNamespace ); |
659 | 650 | } |
660 | 651 | |
661 | 652 | /** |
662 | 653 | * Get the DB key with the initial letter case as specified by the user |
663 | 654 | * |
664 | | - * @return \type{\string} DB key |
| 655 | + * @return String DB key |
665 | 656 | */ |
666 | 657 | function getUserCaseDBKey() { |
667 | 658 | return $this->mUserCaseDBKey; |
— | — | @@ -669,7 +660,7 @@ |
670 | 661 | /** |
671 | 662 | * Get the namespace text of the subject (rather than talk) page |
672 | 663 | * |
673 | | - * @return \type{\string} Namespace text |
| 664 | + * @return String Namespace text |
674 | 665 | */ |
675 | 666 | public function getSubjectNsText() { |
676 | 667 | global $wgContLang; |
— | — | @@ -679,7 +670,7 @@ |
680 | 671 | /** |
681 | 672 | * Get the namespace text of the talk page |
682 | 673 | * |
683 | | - * @return \type{\string} Namespace text |
| 674 | + * @return String Namespace text |
684 | 675 | */ |
685 | 676 | public function getTalkNsText() { |
686 | 677 | global $wgContLang; |
— | — | @@ -689,7 +680,7 @@ |
690 | 681 | /** |
691 | 682 | * Could this title have a corresponding talk page? |
692 | 683 | * |
693 | | - * @return \type{\bool} TRUE or FALSE |
| 684 | + * @return Bool TRUE or FALSE |
694 | 685 | */ |
695 | 686 | public function canTalk() { |
696 | 687 | return( MWNamespace::canTalk( $this->mNamespace ) ); |
— | — | @@ -698,20 +689,20 @@ |
699 | 690 | /** |
700 | 691 | * Get the interwiki prefix (or null string) |
701 | 692 | * |
702 | | - * @return \type{\string} Interwiki prefix |
| 693 | + * @return String Interwiki prefix |
703 | 694 | */ |
704 | 695 | public function getInterwiki() { return $this->mInterwiki; } |
705 | 696 | |
706 | 697 | /** |
707 | 698 | * Get the Title fragment (i.e.\ the bit after the #) in text form |
708 | 699 | * |
709 | | - * @return \type{\string} Title fragment |
| 700 | + * @return String Title fragment |
710 | 701 | */ |
711 | 702 | public function getFragment() { return $this->mFragment; } |
712 | 703 | |
713 | 704 | /** |
714 | 705 | * 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 |
716 | 707 | */ |
717 | 708 | public function getFragmentForURL() { |
718 | 709 | if ( $this->mFragment == '' ) { |
— | — | @@ -724,14 +715,14 @@ |
725 | 716 | /** |
726 | 717 | * Get the default namespace index, for when there is no namespace |
727 | 718 | * |
728 | | - * @return \type{\int} Default namespace index |
| 719 | + * @return Int Default namespace index |
729 | 720 | */ |
730 | 721 | public function getDefaultNamespace() { return $this->mDefaultNamespace; } |
731 | 722 | |
732 | 723 | /** |
733 | 724 | * Get title for search index |
734 | 725 | * |
735 | | - * @return \type{\string} a stripped-down title string ready for the |
| 726 | + * @return String a stripped-down title string ready for the |
736 | 727 | * search index |
737 | 728 | */ |
738 | 729 | public function getIndexTitle() { |
— | — | @@ -741,7 +732,7 @@ |
742 | 733 | /** |
743 | 734 | * Get the prefixed database key form |
744 | 735 | * |
745 | | - * @return \type{\string} the prefixed title, with underscores and |
| 736 | + * @return String the prefixed title, with underscores and |
746 | 737 | * any interwiki and namespace prefixes |
747 | 738 | */ |
748 | 739 | public function getPrefixedDBkey() { |
— | — | @@ -754,7 +745,7 @@ |
755 | 746 | * Get the prefixed title with spaces. |
756 | 747 | * This is the form usually used for display |
757 | 748 | * |
758 | | - * @return \type{\string} the prefixed title, with spaces |
| 749 | + * @return String the prefixed title, with spaces |
759 | 750 | */ |
760 | 751 | public function getPrefixedText() { |
761 | 752 | // @todo FIXME: Bad usage of empty() ? |
— | — | @@ -784,8 +775,7 @@ |
785 | 776 | * Get the prefixed title with spaces, plus any fragment |
786 | 777 | * (part beginning with '#') |
787 | 778 | * |
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 '#' |
790 | 780 | */ |
791 | 781 | public function getFullText() { |
792 | 782 | $text = $this->getPrefixedText(); |
— | — | @@ -798,7 +788,7 @@ |
799 | 789 | /** |
800 | 790 | * Get the base page name, i.e. the leftmost part before any slashes |
801 | 791 | * |
802 | | - * @return \type{\string} Base name |
| 792 | + * @return String Base name |
803 | 793 | */ |
804 | 794 | public function getBaseText() { |
805 | 795 | if ( !MWNamespace::hasSubpages( $this->mNamespace ) ) { |
— | — | @@ -816,7 +806,7 @@ |
817 | 807 | /** |
818 | 808 | * Get the lowest-level subpage name, i.e. the rightmost part after any slashes |
819 | 809 | * |
820 | | - * @return \type{\string} Subpage name |
| 810 | + * @return String Subpage name |
821 | 811 | */ |
822 | 812 | public function getSubpageText() { |
823 | 813 | if ( !MWNamespace::hasSubpages( $this->mNamespace ) ) { |
— | — | @@ -829,7 +819,7 @@ |
830 | 820 | /** |
831 | 821 | * Get a URL-encoded form of the subpage text |
832 | 822 | * |
833 | | - * @return \type{\string} URL-encoded subpage name |
| 823 | + * @return String URL-encoded subpage name |
834 | 824 | */ |
835 | 825 | public function getSubpageUrlForm() { |
836 | 826 | $text = $this->getSubpageText(); |
— | — | @@ -840,7 +830,7 @@ |
841 | 831 | /** |
842 | 832 | * Get a URL-encoded title (not an actual URL) including interwiki |
843 | 833 | * |
844 | | - * @return \type{\string} the URL-encoded form |
| 834 | + * @return String the URL-encoded form |
845 | 835 | */ |
846 | 836 | public function getPrefixedURL() { |
847 | 837 | $s = $this->prefix( $this->mDbkeyform ); |
— | — | @@ -855,8 +845,8 @@ |
856 | 846 | * @param $query \twotypes{\string,\array} an optional query string, not used for interwiki |
857 | 847 | * links. Can be specified as an associative array as well, e.g., |
858 | 848 | * 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 |
861 | 851 | */ |
862 | 852 | public function getFullURL( $query = '', $variant = false ) { |
863 | 853 | global $wgServer, $wgRequest; |
— | — | @@ -902,25 +892,17 @@ |
903 | 893 | * $wgArticlePath will be used. Can be specified as an associative array |
904 | 894 | * as well, e.g., array( 'action' => 'edit' ) (keys and values will be |
905 | 895 | * 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 |
908 | 898 | */ |
909 | 899 | public function getLocalURL( $query = '', $variant = false ) { |
910 | 900 | global $wgArticlePath, $wgScript, $wgServer, $wgRequest; |
911 | | - global $wgVariantArticlePath, $wgContLang, $wgUser; |
| 901 | + global $wgVariantArticlePath, $wgContLang; |
912 | 902 | |
913 | 903 | if ( is_array( $query ) ) { |
914 | 904 | $query = wfArrayToCGI( $query ); |
915 | 905 | } |
916 | 906 | |
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 | | - |
925 | 907 | if ( $this->isExternal() ) { |
926 | 908 | $url = $this->getFullURL(); |
927 | 909 | if ( $query ) { |
— | — | @@ -992,12 +974,12 @@ |
993 | 975 | * The result obviously should not be URL-escaped, but does need to be |
994 | 976 | * HTML-escaped if it's being output in HTML. |
995 | 977 | * |
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 |
997 | 979 | * 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 |
999 | 981 | * for external links. Default is "false" (same variant as current page, |
1000 | 982 | * for anonymous users). |
1001 | | - * @return \type{\string} the URL |
| 983 | + * @return String the URL |
1002 | 984 | */ |
1003 | 985 | public function getLinkUrl( $query = array(), $variant = false ) { |
1004 | 986 | wfProfileIn( __METHOD__ ); |
— | — | @@ -1016,8 +998,8 @@ |
1017 | 999 | * Get an HTML-escaped version of the URL form, suitable for |
1018 | 1000 | * using in a link, without a server name or fragment |
1019 | 1001 | * |
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 |
1022 | 1004 | */ |
1023 | 1005 | public function escapeLocalURL( $query = '' ) { |
1024 | 1006 | return htmlspecialchars( $this->getLocalURL( $query ) ); |
— | — | @@ -1027,8 +1009,8 @@ |
1028 | 1010 | * Get an HTML-escaped version of the URL form, suitable for |
1029 | 1011 | * using in a link, including the server name and fragment |
1030 | 1012 | * |
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 |
1033 | 1015 | */ |
1034 | 1016 | public function escapeFullURL( $query = '' ) { |
1035 | 1017 | return htmlspecialchars( $this->getFullURL( $query ) ); |
— | — | @@ -1039,13 +1021,14 @@ |
1040 | 1022 | * - Used in various Squid-related code, in case we have a different |
1041 | 1023 | * internal hostname for the server from the exposed one. |
1042 | 1024 | * |
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 |
1046 | 1028 | */ |
1047 | 1029 | 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 ); |
1050 | 1033 | wfRunHooks( 'GetInternalURL', array( &$this, &$url, $query ) ); |
1051 | 1034 | return $url; |
1052 | 1035 | } |
— | — | @@ -1053,7 +1036,7 @@ |
1054 | 1037 | /** |
1055 | 1038 | * Get the edit URL for this Title |
1056 | 1039 | * |
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 |
1058 | 1041 | * interwiki link |
1059 | 1042 | */ |
1060 | 1043 | public function getEditURL() { |
— | — | @@ -1069,7 +1052,7 @@ |
1070 | 1053 | * Get the HTML-escaped displayable text form. |
1071 | 1054 | * Used for the title field in <a> tags. |
1072 | 1055 | * |
1073 | | - * @return \type{\string} the text, including any prefixes |
| 1056 | + * @return String the text, including any prefixes |
1074 | 1057 | */ |
1075 | 1058 | public function getEscapedText() { |
1076 | 1059 | return htmlspecialchars( $this->getPrefixedText() ); |
— | — | @@ -1078,7 +1061,7 @@ |
1079 | 1062 | /** |
1080 | 1063 | * Is this Title interwiki? |
1081 | 1064 | * |
1082 | | - * @return \type{\bool} |
| 1065 | + * @return Bool |
1083 | 1066 | */ |
1084 | 1067 | public function isExternal() { |
1085 | 1068 | return ( $this->mInterwiki != '' ); |
— | — | @@ -1087,8 +1070,8 @@ |
1088 | 1071 | /** |
1089 | 1072 | * Is this page "semi-protected" - the *only* protection is autoconfirm? |
1090 | 1073 | * |
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 |
1093 | 1076 | */ |
1094 | 1077 | public function isSemiProtected( $action = 'edit' ) { |
1095 | 1078 | if ( $this->exists() ) { |
— | — | @@ -1113,9 +1096,9 @@ |
1114 | 1097 | /** |
1115 | 1098 | * Does the title correspond to a protected article? |
1116 | 1099 | * |
1117 | | - * @param $action \type{\string} the action the page is protected from, |
| 1100 | + * @param $action String the action the page is protected from, |
1118 | 1101 | * by default checks all actions. |
1119 | | - * @return \type{\bool} |
| 1102 | + * @return Bool |
1120 | 1103 | */ |
1121 | 1104 | public function isProtected( $action = '' ) { |
1122 | 1105 | global $wgRestrictionLevels; |
— | — | @@ -1145,7 +1128,7 @@ |
1146 | 1129 | /** |
1147 | 1130 | * Is this a conversion table for the LanguageConverter? |
1148 | 1131 | * |
1149 | | - * @return \type{\bool} |
| 1132 | + * @return Bool |
1150 | 1133 | */ |
1151 | 1134 | public function isConversionTable() { |
1152 | 1135 | if( |
— | — | @@ -1162,7 +1145,7 @@ |
1163 | 1146 | /** |
1164 | 1147 | * Is $wgUser watching this page? |
1165 | 1148 | * |
1166 | | - * @return \type{\bool} |
| 1149 | + * @return Bool |
1167 | 1150 | */ |
1168 | 1151 | public function userIsWatching() { |
1169 | 1152 | global $wgUser; |
— | — | @@ -1187,25 +1170,26 @@ |
1188 | 1171 | * |
1189 | 1172 | * May provide false positives, but should never provide a false negative. |
1190 | 1173 | * |
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 |
1193 | 1176 | */ |
1194 | 1177 | public function quickUserCan( $action ) { |
1195 | 1178 | return $this->userCan( $action, false ); |
1196 | 1179 | } |
1197 | 1180 | |
1198 | 1181 | /** |
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 |
1200 | 1183 | * by $wgNamespaceProtection. |
1201 | 1184 | * |
1202 | 1185 | * @param $user User object to check permissions |
1203 | 1186 | * @return Bool |
1204 | 1187 | */ |
1205 | | - public function isNamespaceProtected() { |
1206 | | - global $wgNamespaceProtection, $wgUser; |
| 1188 | + public function isNamespaceProtected( User $user ) { |
| 1189 | + global $wgNamespaceProtection; |
| 1190 | + |
1207 | 1191 | if ( isset( $wgNamespaceProtection[$this->mNamespace] ) ) { |
1208 | 1192 | foreach ( (array)$wgNamespaceProtection[$this->mNamespace] as $right ) { |
1209 | | - if ( $right != '' && !$wgUser->isAllowed( $right ) ) { |
| 1193 | + if ( $right != '' && !$user->isAllowed( $right ) ) { |
1210 | 1194 | return true; |
1211 | 1195 | } |
1212 | 1196 | } |
— | — | @@ -1216,9 +1200,9 @@ |
1217 | 1201 | /** |
1218 | 1202 | * Can $wgUser perform $action on this page? |
1219 | 1203 | * |
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 |
1223 | 1207 | */ |
1224 | 1208 | public function userCan( $action, $doExpensiveQueries = true ) { |
1225 | 1209 | global $wgUser; |
— | — | @@ -1238,14 +1222,6 @@ |
1239 | 1223 | * @return Array of arguments to wfMsg to explain permissions problems. |
1240 | 1224 | */ |
1241 | 1225 | 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 | | - |
1250 | 1226 | $errors = $this->getUserPermissionsErrorsInternal( $action, $user, $doExpensiveQueries ); |
1251 | 1227 | |
1252 | 1228 | // Remove the errors being ignored. |
— | — | @@ -1316,8 +1292,6 @@ |
1317 | 1293 | $errors[] = array( 'cant-move-to-user-page' ); |
1318 | 1294 | } |
1319 | 1295 | } elseif ( !$user->isAllowed( $action, $ns ) ) { |
1320 | | - $return = null; |
1321 | | - |
1322 | 1296 | // We avoid expensive display logic for quickUserCan's and such |
1323 | 1297 | $groups = false; |
1324 | 1298 | if ( !$short ) { |
— | — | @@ -1368,10 +1342,18 @@ |
1369 | 1343 | |
1370 | 1344 | /** |
1371 | 1345 | * 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 |
1373 | 1354 | */ |
1374 | 1355 | private function checkPermissionHooks( $action, $user, $errors, $doExpensiveQueries, $short ) { |
1375 | 1356 | // Use getUserPermissionsErrors instead |
| 1357 | + $result = ''; |
1376 | 1358 | if ( !wfRunHooks( 'userCan', array( &$this, &$user, $action, &$result ) ) ) { |
1377 | 1359 | return $result ? array() : array( array( 'badaccess-group0' ) ); |
1378 | 1360 | } |
— | — | @@ -1390,7 +1372,14 @@ |
1391 | 1373 | |
1392 | 1374 | /** |
1393 | 1375 | * 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 |
1395 | 1384 | */ |
1396 | 1385 | private function checkSpecialsAndNSPermissions( $action, $user, $errors, $doExpensiveQueries, $short ) { |
1397 | 1386 | # Only 'createaccount' and 'execute' can be performed on |
— | — | @@ -1401,7 +1390,7 @@ |
1402 | 1391 | } |
1403 | 1392 | |
1404 | 1393 | # Check $wgNamespaceProtection for restricted namespaces |
1405 | | - if ( $this->isNamespaceProtected() ) { |
| 1394 | + if ( $this->isNamespaceProtected( $user ) ) { |
1406 | 1395 | $ns = $this->mNamespace == NS_MAIN ? |
1407 | 1396 | wfMsg( 'nstab-main' ) : $this->getNsText(); |
1408 | 1397 | $errors[] = $this->mNamespace == NS_MEDIAWIKI ? |
— | — | @@ -1413,7 +1402,14 @@ |
1414 | 1403 | |
1415 | 1404 | /** |
1416 | 1405 | * 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 |
1418 | 1414 | */ |
1419 | 1415 | private function checkCSSandJSPermissions( $action, $user, $errors, $doExpensiveQueries, $short ) { |
1420 | 1416 | # Protect css/js subpages of user pages |
— | — | @@ -1435,7 +1431,14 @@ |
1436 | 1432 | * Check against page_restrictions table requirements on this |
1437 | 1433 | * page. The user must possess all required rights for this |
1438 | 1434 | * 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 |
1440 | 1443 | */ |
1441 | 1444 | private function checkPageRestrictions( $action, $user, $errors, $doExpensiveQueries, $short ) { |
1442 | 1445 | foreach ( $this->getRestrictions( $action ) as $right ) { |
— | — | @@ -1462,7 +1465,14 @@ |
1463 | 1466 | |
1464 | 1467 | /** |
1465 | 1468 | * 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 |
1467 | 1477 | */ |
1468 | 1478 | private function checkCascadingSourcesRestrictions( $action, $user, $errors, $doExpensiveQueries, $short ) { |
1469 | 1479 | if ( $doExpensiveQueries && !$this->isCssJsSubpage() ) { |
— | — | @@ -1494,7 +1504,14 @@ |
1495 | 1505 | |
1496 | 1506 | /** |
1497 | 1507 | * 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 |
1499 | 1516 | */ |
1500 | 1517 | private function checkActionPermissions( $action, $user, $errors, $doExpensiveQueries, $short ) { |
1501 | 1518 | if ( $action == 'protect' ) { |
— | — | @@ -1535,7 +1552,14 @@ |
1536 | 1553 | |
1537 | 1554 | /** |
1538 | 1555 | * 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 |
1540 | 1564 | */ |
1541 | 1565 | private function checkUserBlock( $action, $user, $errors, $doExpensiveQueries, $short ) { |
1542 | 1566 | if( !$doExpensiveQueries ) { |
— | — | @@ -1548,8 +1572,14 @@ |
1549 | 1573 | $errors[] = array( 'confirmedittext' ); |
1550 | 1574 | } |
1551 | 1575 | |
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 ) { |
1554 | 1584 | $block = $user->mBlock; |
1555 | 1585 | |
1556 | 1586 | // This is from OutputPage::blockedPage |
— | — | @@ -1569,29 +1599,16 @@ |
1570 | 1600 | } |
1571 | 1601 | |
1572 | 1602 | $link = '[[' . $wgContLang->getNsText( NS_USER ) . ":{$name}|{$name}]]"; |
1573 | | - $blockid = $block->mId; |
| 1603 | + $blockid = $block->getId(); |
1574 | 1604 | $blockExpiry = $user->mBlock->mExpiry; |
1575 | 1605 | $blockTimestamp = $wgLang->timeanddate( wfTimestamp( TS_MW, $user->mBlock->mTimestamp ), true ); |
1576 | 1606 | 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(); |
1591 | 1608 | } else { |
1592 | 1609 | $blockExpiry = $wgLang->timeanddate( wfTimestamp( TS_MW, $blockExpiry ), true ); |
1593 | 1610 | } |
1594 | 1611 | |
1595 | | - $intended = $user->mBlock->mAddress; |
| 1612 | + $intended = strval( $user->mBlock->getTarget() ); |
1596 | 1613 | |
1597 | 1614 | $errors[] = array( ( $block->mAuto ? 'autoblockedtext' : 'blockedtext' ), $link, $reason, $ip, $name, |
1598 | 1615 | $blockid, $blockExpiry, $intended, $blockTimestamp ); |
— | — | @@ -1605,11 +1622,11 @@ |
1606 | 1623 | * which checks ONLY that previously checked by userCan (i.e. it leaves out |
1607 | 1624 | * checks on wfReadOnly() and blocks) |
1608 | 1625 | * |
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. |
1614 | 1631 | */ |
1615 | 1632 | protected function getUserPermissionsErrorsInternal( $action, $user, $doExpensiveQueries = true, $short = false ) { |
1616 | 1633 | wfProfileIn( __METHOD__ ); |
— | — | @@ -1638,8 +1655,9 @@ |
1639 | 1656 | |
1640 | 1657 | /** |
1641 | 1658 | * Is this title subject to title protection? |
| 1659 | + * Title protection is the one applied against creation of such title. |
1642 | 1660 | * |
1643 | | - * @return \type{\mixed} An associative array representing any existent title |
| 1661 | + * @return Mixed An associative array representing any existent title |
1644 | 1662 | * protection, or false if there's none. |
1645 | 1663 | */ |
1646 | 1664 | private function getTitleProtection() { |
— | — | @@ -1668,9 +1686,9 @@ |
1669 | 1687 | /** |
1670 | 1688 | * Update the title protection status |
1671 | 1689 | * |
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 |
1675 | 1693 | * @return boolean true |
1676 | 1694 | */ |
1677 | 1695 | public function updateTitleProtection( $create_perm, $reason, $expiry ) { |
— | — | @@ -1686,10 +1704,10 @@ |
1687 | 1705 | |
1688 | 1706 | $dbw = wfGetDB( DB_MASTER ); |
1689 | 1707 | |
1690 | | - $encodedExpiry = Block::encodeExpiry( $expiry, $dbw ); |
| 1708 | + $encodedExpiry = $dbw->encodeExpiry( $expiry ); |
1691 | 1709 | |
1692 | 1710 | $expiry_description = ''; |
1693 | | - if ( $encodedExpiry != 'infinity' ) { |
| 1711 | + if ( $encodedExpiry != $dbw->getInfinity() ) { |
1694 | 1712 | $expiry_description = ' (' . wfMsgForContent( 'protect-expiring', $wgContLang->timeanddate( $expiry ), |
1695 | 1713 | $wgContLang->date( $expiry ) , $wgContLang->time( $expiry ) ) . ')'; |
1696 | 1714 | } else { |
— | — | @@ -1698,21 +1716,23 @@ |
1699 | 1717 | |
1700 | 1718 | # Update protection table |
1701 | 1719 | if ( $create_perm != '' ) { |
1702 | | - $dbw->replace( 'protected_titles', array( array( 'pt_namespace', 'pt_title' ) ), |
1703 | | - array( |
| 1720 | + $this->mTitleProtection = array( |
1704 | 1721 | 'pt_namespace' => $namespace, |
1705 | 1722 | 'pt_title' => $title, |
1706 | 1723 | 'pt_create_perm' => $create_perm, |
1707 | | - 'pt_timestamp' => Block::encodeExpiry( wfTimestampNow(), $dbw ), |
| 1724 | + 'pt_timestamp' => $dbw->encodeExpiry( wfTimestampNow() ), |
1708 | 1725 | 'pt_expiry' => $encodedExpiry, |
1709 | 1726 | 'pt_user' => $wgUser->getId(), |
1710 | 1727 | 'pt_reason' => $reason, |
1711 | | - ), __METHOD__ |
1712 | | - ); |
| 1728 | + ); |
| 1729 | + $dbw->replace( 'protected_titles', array( array( 'pt_namespace', 'pt_title' ) ), |
| 1730 | + $this->mTitleProtection, __METHOD__ ); |
1713 | 1731 | } else { |
1714 | 1732 | $dbw->delete( 'protected_titles', array( 'pt_namespace' => $namespace, |
1715 | 1733 | 'pt_title' => $title ), __METHOD__ ); |
| 1734 | + $this->mTitleProtection = false; |
1716 | 1735 | } |
| 1736 | + |
1717 | 1737 | # Update the protection log |
1718 | 1738 | if ( $dbw->affectedRows() ) { |
1719 | 1739 | $log = new LogPage( 'protect' ); |
— | — | @@ -1739,13 +1759,14 @@ |
1740 | 1760 | array( 'pt_namespace' => $this->getNamespace(), 'pt_title' => $this->getDBkey() ), |
1741 | 1761 | __METHOD__ |
1742 | 1762 | ); |
| 1763 | + $this->mTitleProtection = false; |
1743 | 1764 | } |
1744 | 1765 | |
1745 | 1766 | /** |
1746 | 1767 | * Would anybody with sufficient privileges be able to move this page? |
1747 | 1768 | * Some pages just aren't movable. |
1748 | 1769 | * |
1749 | | - * @return \type{\bool} TRUE or FALSE |
| 1770 | + * @return Bool TRUE or FALSE |
1750 | 1771 | */ |
1751 | 1772 | public function isMovable() { |
1752 | 1773 | return MWNamespace::isMovable( $this->getNamespace() ) && $this->getInterwiki() == ''; |
— | — | @@ -1754,7 +1775,7 @@ |
1755 | 1776 | /** |
1756 | 1777 | * Can $wgUser read this page? |
1757 | 1778 | * |
1758 | | - * @return \type{\bool} |
| 1779 | + * @return Bool |
1759 | 1780 | * @todo fold these checks into userCan() |
1760 | 1781 | */ |
1761 | 1782 | public function userCanRead() { |
— | — | @@ -1802,47 +1823,36 @@ |
1803 | 1824 | } else { |
1804 | 1825 | global $wgWhitelistRead; |
1805 | 1826 | |
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' ) ) { |
1811 | 1830 | return true; |
1812 | 1831 | } |
1813 | 1832 | |
1814 | | - /** |
1815 | | - * Bail out if there isn't whitelist |
1816 | | - */ |
| 1833 | + # Bail out if there isn't whitelist |
1817 | 1834 | if ( !is_array( $wgWhitelistRead ) ) { |
1818 | 1835 | return false; |
1819 | 1836 | } |
1820 | 1837 | |
1821 | | - /** |
1822 | | - * Check for explicit whitelisting |
1823 | | - */ |
| 1838 | + # Check for explicit whitelisting |
1824 | 1839 | $name = $this->getPrefixedText(); |
1825 | 1840 | $dbName = $this->getPrefixedDBKey(); |
1826 | 1841 | // Check with and without underscores |
1827 | 1842 | if ( in_array( $name, $wgWhitelistRead, true ) || in_array( $dbName, $wgWhitelistRead, true ) ) |
1828 | 1843 | return true; |
1829 | 1844 | |
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 |
1834 | 1847 | if ( $this->getNamespace() == NS_MAIN ) { |
1835 | 1848 | if ( in_array( ':' . $name, $wgWhitelistRead ) ) { |
1836 | 1849 | return true; |
1837 | 1850 | } |
1838 | 1851 | } |
1839 | 1852 | |
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 |
1844 | 1854 | if ( $this->getNamespace() == NS_SPECIAL ) { |
1845 | 1855 | $name = $this->getDBkey(); |
1846 | | - list( $name, /* $subpage */ ) = SpecialPage::resolveAliasWithSubpage( $name ); |
| 1856 | + list( $name, /* $subpage */ ) = SpecialPageFactory::resolveAlias( $name ); |
1847 | 1857 | if ( $name === false ) { |
1848 | 1858 | # Invalid special page, but we show standard login required message |
1849 | 1859 | return false; |
— | — | @@ -1859,9 +1869,22 @@ |
1860 | 1870 | } |
1861 | 1871 | |
1862 | 1872 | /** |
| 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 | + /** |
1863 | 1886 | * Is this a talk page of some sort? |
1864 | 1887 | * |
1865 | | - * @return \type{\bool} |
| 1888 | + * @return Bool |
1866 | 1889 | */ |
1867 | 1890 | public function isTalkPage() { |
1868 | 1891 | return MWNamespace::isTalk( $this->getNamespace() ); |
— | — | @@ -1870,7 +1893,7 @@ |
1871 | 1894 | /** |
1872 | 1895 | * Is this a subpage? |
1873 | 1896 | * |
1874 | | - * @return \type{\bool} |
| 1897 | + * @return Bool |
1875 | 1898 | */ |
1876 | 1899 | public function isSubpage() { |
1877 | 1900 | return MWNamespace::hasSubpages( $this->mNamespace ) |
— | — | @@ -1881,7 +1904,7 @@ |
1882 | 1905 | /** |
1883 | 1906 | * Does this have subpages? (Warning, usually requires an extra DB query.) |
1884 | 1907 | * |
1885 | | - * @return \type{\bool} |
| 1908 | + * @return Bool |
1886 | 1909 | */ |
1887 | 1910 | public function hasSubpages() { |
1888 | 1911 | if ( !MWNamespace::hasSubpages( $this->mNamespace ) ) { |
— | — | @@ -1907,7 +1930,7 @@ |
1908 | 1931 | /** |
1909 | 1932 | * Get all subpages of this page. |
1910 | 1933 | * |
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 |
1912 | 1935 | * @return mixed TitleArray, or empty array if this page's namespace |
1913 | 1936 | * doesn't allow subpages |
1914 | 1937 | */ |
— | — | @@ -1937,7 +1960,7 @@ |
1938 | 1961 | * Could this page contain custom CSS or JavaScript, based |
1939 | 1962 | * on the title? |
1940 | 1963 | * |
1941 | | - * @return \type{\bool} |
| 1964 | + * @return Bool |
1942 | 1965 | */ |
1943 | 1966 | public function isCssOrJsPage() { |
1944 | 1967 | return $this->mNamespace == NS_MEDIAWIKI |
— | — | @@ -1946,7 +1969,7 @@ |
1947 | 1970 | |
1948 | 1971 | /** |
1949 | 1972 | * Is this a .css or .js subpage of a user page? |
1950 | | - * @return \type{\bool} |
| 1973 | + * @return Bool |
1951 | 1974 | */ |
1952 | 1975 | public function isCssJsSubpage() { |
1953 | 1976 | return ( NS_USER == $this->mNamespace and preg_match( "/\\/.*\\.(?:css|js)$/", $this->mTextform ) ); |
— | — | @@ -1954,21 +1977,12 @@ |
1955 | 1978 | |
1956 | 1979 | /** |
1957 | 1980 | * Is this a *valid* .css or .js subpage of a user page? |
1958 | | - * Check that the corresponding skin exists |
1959 | 1981 | * |
1960 | | - * @return \type{\bool} |
| 1982 | + * @return Bool |
| 1983 | + * @deprecated since 1.17 |
1961 | 1984 | */ |
1962 | 1985 | 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(); |
1973 | 1987 | } |
1974 | 1988 | |
1975 | 1989 | /** |
— | — | @@ -1985,7 +1999,7 @@ |
1986 | 2000 | /** |
1987 | 2001 | * Is this a .css subpage of a user page? |
1988 | 2002 | * |
1989 | | - * @return \type{\bool} |
| 2003 | + * @return Bool |
1990 | 2004 | */ |
1991 | 2005 | public function isCssSubpage() { |
1992 | 2006 | return ( NS_USER == $this->mNamespace && preg_match( "/\\/.*\\.css$/", $this->mTextform ) ); |
— | — | @@ -1994,7 +2008,7 @@ |
1995 | 2009 | /** |
1996 | 2010 | * Is this a .js subpage of a user page? |
1997 | 2011 | * |
1998 | | - * @return \type{\bool} |
| 2012 | + * @return Bool |
1999 | 2013 | */ |
2000 | 2014 | public function isJsSubpage() { |
2001 | 2015 | return ( NS_USER == $this->mNamespace && preg_match( "/\\/.*\\.js$/", $this->mTextform ) ); |
— | — | @@ -2031,7 +2045,7 @@ |
2032 | 2046 | /** |
2033 | 2047 | * Cascading protection: Return true if cascading restrictions apply to this page, false if not. |
2034 | 2048 | * |
2035 | | - * @return \type{\bool} If the page is subject to cascading restrictions. |
| 2049 | + * @return Bool If the page is subject to cascading restrictions. |
2036 | 2050 | */ |
2037 | 2051 | public function isCascadeProtected() { |
2038 | 2052 | list( $sources, /* $restrictions */ ) = $this->getCascadeProtectionSources( false ); |
— | — | @@ -2041,15 +2055,15 @@ |
2042 | 2056 | /** |
2043 | 2057 | * Cascading protection: Get the source of any cascading restrictions on this page. |
2044 | 2058 | * |
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 |
2046 | 2060 | * 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. |
2052 | 2065 | */ |
2053 | 2066 | public function getCascadeProtectionSources( $getPages = true ) { |
| 2067 | + global $wgContLang; |
2054 | 2068 | $pagerestrictions = array(); |
2055 | 2069 | |
2056 | 2070 | if ( isset( $this->mCascadeSources ) && $getPages ) { |
— | — | @@ -2095,7 +2109,7 @@ |
2096 | 2110 | $purgeExpired = false; |
2097 | 2111 | |
2098 | 2112 | foreach ( $res as $row ) { |
2099 | | - $expiry = Block::decodeExpiry( $row->pr_expiry ); |
| 2113 | + $expiry = $wgContLang->formatExpiry( $row->pr_expiry, TS_MW ); |
2100 | 2114 | if ( $expiry > $now ) { |
2101 | 2115 | if ( $getPages ) { |
2102 | 2116 | $page_id = $row->pr_page; |
— | — | @@ -2125,8 +2139,6 @@ |
2126 | 2140 | Title::purgeExpiredRestrictions(); |
2127 | 2141 | } |
2128 | 2142 | |
2129 | | - wfProfileOut( __METHOD__ ); |
2130 | | - |
2131 | 2143 | if ( $getPages ) { |
2132 | 2144 | $this->mCascadeSources = $sources; |
2133 | 2145 | $this->mCascadingRestrictions = $pagerestrictions; |
— | — | @@ -2134,6 +2146,7 @@ |
2135 | 2147 | $this->mHasCascadingRestrictions = $sources; |
2136 | 2148 | } |
2137 | 2149 | |
| 2150 | + wfProfileOut( __METHOD__ ); |
2138 | 2151 | return array( $sources, $pagerestrictions ); |
2139 | 2152 | } |
2140 | 2153 | |
— | — | @@ -2153,15 +2166,14 @@ |
2154 | 2167 | /** |
2155 | 2168 | * Loads a string into mRestrictions array |
2156 | 2169 | * |
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 |
2159 | 2172 | * restrictions from page table (pre 1.10) |
2160 | 2173 | */ |
2161 | 2174 | private function loadRestrictionsFromResultWrapper( $res, $oldFashionedRestrictions = null ) { |
2162 | 2175 | $rows = array(); |
2163 | | - $dbr = wfGetDB( DB_SLAVE ); |
2164 | 2176 | |
2165 | | - while ( $row = $dbr->fetchObject( $res ) ) { |
| 2177 | + foreach ( $res as $row ) { |
2166 | 2178 | $rows[] = $row; |
2167 | 2179 | } |
2168 | 2180 | |
— | — | @@ -2170,20 +2182,22 @@ |
2171 | 2183 | |
2172 | 2184 | /** |
2173 | 2185 | * 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. |
2175 | 2188 | * |
2176 | 2189 | * @param $rows array of db result objects |
2177 | 2190 | * @param $oldFashionedRestrictions string comma-separated list of page |
2178 | 2191 | * restrictions from page table (pre 1.10) |
2179 | 2192 | */ |
2180 | 2193 | public function loadRestrictionsFromRows( $rows, $oldFashionedRestrictions = null ) { |
| 2194 | + global $wgContLang; |
2181 | 2195 | $dbr = wfGetDB( DB_SLAVE ); |
2182 | 2196 | |
2183 | 2197 | $restrictionTypes = $this->getRestrictionTypes(); |
2184 | 2198 | |
2185 | 2199 | foreach ( $restrictionTypes as $type ) { |
2186 | 2200 | $this->mRestrictions[$type] = array(); |
2187 | | - $this->mRestrictionsExpiry[$type] = Block::decodeExpiry( '' ); |
| 2201 | + $this->mRestrictionsExpiry[$type] = $wgContLang->formatExpiry( '', TS_MW ); |
2188 | 2202 | } |
2189 | 2203 | |
2190 | 2204 | $this->mCascadeRestriction = false; |
— | — | @@ -2217,17 +2231,16 @@ |
2218 | 2232 | $now = wfTimestampNow(); |
2219 | 2233 | $purgeExpired = false; |
2220 | 2234 | |
| 2235 | + # Cycle through all the restrictions. |
2221 | 2236 | foreach ( $rows as $row ) { |
2222 | | - # Cycle through all the restrictions. |
2223 | 2237 | |
2224 | 2238 | // Don't take care of restrictions types that aren't allowed |
2225 | | - |
2226 | 2239 | if ( !in_array( $row->pr_type, $restrictionTypes ) ) |
2227 | 2240 | continue; |
2228 | 2241 | |
2229 | 2242 | // This code should be refactored, now that it's being used more generally, |
2230 | 2243 | // 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 ); |
2232 | 2245 | |
2233 | 2246 | // Only apply the restrictions if they haven't expired! |
2234 | 2247 | if ( !$expiry || $expiry > $now ) { |
— | — | @@ -2252,16 +2265,21 @@ |
2253 | 2266 | /** |
2254 | 2267 | * Load restrictions from the page_restrictions table |
2255 | 2268 | * |
2256 | | - * @param $oldFashionedRestrictions string comma-separated list of page |
| 2269 | + * @param $oldFashionedRestrictions String comma-separated list of page |
2257 | 2270 | * restrictions from page table (pre 1.10) |
2258 | 2271 | */ |
2259 | 2272 | public function loadRestrictions( $oldFashionedRestrictions = null ) { |
| 2273 | + global $wgContLang; |
2260 | 2274 | if ( !$this->mRestrictionsLoaded ) { |
2261 | 2275 | if ( $this->exists() ) { |
2262 | 2276 | $dbr = wfGetDB( DB_SLAVE ); |
2263 | 2277 | |
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 | + ); |
2266 | 2284 | |
2267 | 2285 | $this->loadRestrictionsFromResultWrapper( $res, $oldFashionedRestrictions ); |
2268 | 2286 | } else { |
— | — | @@ -2269,7 +2287,7 @@ |
2270 | 2288 | |
2271 | 2289 | if ( $title_protection ) { |
2272 | 2290 | $now = wfTimestampNow(); |
2273 | | - $expiry = Block::decodeExpiry( $title_protection['pt_expiry'] ); |
| 2291 | + $expiry = $wgContLang->formatExpiry( $title_protection['pt_expiry'], TS_MW ); |
2274 | 2292 | |
2275 | 2293 | if ( !$expiry || $expiry > $now ) { |
2276 | 2294 | // Apply the restrictions |
— | — | @@ -2277,9 +2295,10 @@ |
2278 | 2296 | $this->mRestrictions['create'] = explode( ',', trim( $title_protection['pt_create_perm'] ) ); |
2279 | 2297 | } else { // Get rid of the old restrictions |
2280 | 2298 | Title::purgeExpiredRestrictions(); |
| 2299 | + $this->mTitleProtection = false; |
2281 | 2300 | } |
2282 | 2301 | } else { |
2283 | | - $this->mRestrictionsExpiry['create'] = Block::decodeExpiry( '' ); |
| 2302 | + $this->mRestrictionsExpiry['create'] = $wgContLang->formatExpiry( '', TS_MW ); |
2284 | 2303 | } |
2285 | 2304 | $this->mRestrictionsLoaded = true; |
2286 | 2305 | } |
— | — | @@ -2307,8 +2326,8 @@ |
2308 | 2327 | /** |
2309 | 2328 | * Accessor/initialisation for mRestrictions |
2310 | 2329 | * |
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 |
2313 | 2332 | */ |
2314 | 2333 | public function getRestrictions( $action ) { |
2315 | 2334 | if ( !$this->mRestrictionsLoaded ) { |
— | — | @@ -2322,7 +2341,7 @@ |
2323 | 2342 | /** |
2324 | 2343 | * Get the expiry time for the restriction against a given action |
2325 | 2344 | * |
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 |
2327 | 2346 | * or not protected at all, or false if the action is not recognised. |
2328 | 2347 | */ |
2329 | 2348 | public function getRestrictionExpiry( $action ) { |
— | — | @@ -2400,16 +2419,16 @@ |
2401 | 2420 | * Get the article ID for this Title from the link cache, |
2402 | 2421 | * adding it if necessary |
2403 | 2422 | * |
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 |
2405 | 2424 | * for update |
2406 | | - * @return \type{\int} the ID |
| 2425 | + * @return Int the ID |
2407 | 2426 | */ |
2408 | 2427 | public function getArticleID( $flags = 0 ) { |
2409 | 2428 | if ( $this->getNamespace() < 0 ) { |
2410 | 2429 | return $this->mArticleID = 0; |
2411 | 2430 | } |
2412 | 2431 | $linkCache = LinkCache::singleton(); |
2413 | | - if ( $flags & GAID_FOR_UPDATE ) { |
| 2432 | + if ( $flags & self::GAID_FOR_UPDATE ) { |
2414 | 2433 | $oldUpdate = $linkCache->forUpdate( true ); |
2415 | 2434 | $linkCache->clearLink( $this ); |
2416 | 2435 | $this->mArticleID = $linkCache->addLinkObj( $this ); |
— | — | @@ -2426,8 +2445,8 @@ |
2427 | 2446 | * Is this an article that is a redirect page? |
2428 | 2447 | * Uses link cache, adding it if necessary |
2429 | 2448 | * |
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 |
2432 | 2451 | */ |
2433 | 2452 | public function isRedirect( $flags = 0 ) { |
2434 | 2453 | if ( !is_null( $this->mRedirect ) ) { |
— | — | @@ -2447,8 +2466,8 @@ |
2448 | 2467 | * What is the length of this page? |
2449 | 2468 | * Uses link cache, adding it if necessary |
2450 | 2469 | * |
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 |
2453 | 2472 | */ |
2454 | 2473 | public function getLength( $flags = 0 ) { |
2455 | 2474 | if ( $this->mLength != -1 ) { |
— | — | @@ -2467,8 +2486,8 @@ |
2468 | 2487 | /** |
2469 | 2488 | * What is the page_latest field for this page? |
2470 | 2489 | * |
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 |
2473 | 2492 | */ |
2474 | 2493 | public function getLatestRevID( $flags = 0 ) { |
2475 | 2494 | if ( $this->mLatestID !== false ) { |
— | — | @@ -2488,7 +2507,11 @@ |
2489 | 2508 | * This clears some fields in this object, and clears any associated |
2490 | 2509 | * keys in the "bad links" section of the link cache. |
2491 | 2510 | * |
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 |
2493 | 2516 | */ |
2494 | 2517 | public function resetArticleID( $newid ) { |
2495 | 2518 | $linkCache = LinkCache::singleton(); |
— | — | @@ -2509,7 +2532,7 @@ |
2510 | 2533 | /** |
2511 | 2534 | * Updates page_touched for this page; called from LinksUpdate.php |
2512 | 2535 | * |
2513 | | - * @return \type{\bool} true if the update succeded |
| 2536 | + * @return Bool true if the update succeded |
2514 | 2537 | */ |
2515 | 2538 | public function invalidateCache() { |
2516 | 2539 | if ( wfReadOnly() ) { |
— | — | @@ -2530,15 +2553,16 @@ |
2531 | 2554 | * Prefix some arbitrary text with the namespace or interwiki prefix |
2532 | 2555 | * of this object |
2533 | 2556 | * |
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 |
2536 | 2559 | * @private |
2537 | 2560 | */ |
2538 | | - /* private */ function prefix( $name ) { |
| 2561 | + private function prefix( $name ) { |
2539 | 2562 | $p = ''; |
2540 | 2563 | if ( $this->mInterwiki != '' ) { |
2541 | 2564 | $p = $this->mInterwiki . ':'; |
2542 | 2565 | } |
| 2566 | + |
2543 | 2567 | if ( 0 != $this->mNamespace ) { |
2544 | 2568 | $p .= $this->getNsText() . ':'; |
2545 | 2569 | } |
— | — | @@ -2550,7 +2574,7 @@ |
2551 | 2575 | * Note that this doesn't pick up many things that could be wrong with titles, but that |
2552 | 2576 | * replacing this regex with something valid will make many titles valid. |
2553 | 2577 | * |
2554 | | - * @return string regex string |
| 2578 | + * @return String regex string |
2555 | 2579 | */ |
2556 | 2580 | static function getTitleInvalidRegex() { |
2557 | 2581 | static $rxTc = false; |
— | — | @@ -2575,7 +2599,7 @@ |
2576 | 2600 | /** |
2577 | 2601 | * Capitalize a text string for a title if it belongs to a namespace that capitalizes |
2578 | 2602 | * |
2579 | | - * @param $text string containing title to capitalize |
| 2603 | + * @param $text String containing title to capitalize |
2580 | 2604 | * @param $ns int namespace index, defaults to NS_MAIN |
2581 | 2605 | * @return String containing capitalized title |
2582 | 2606 | */ |
— | — | @@ -2598,14 +2622,12 @@ |
2599 | 2623 | * namespace prefixes, sets the other forms, and canonicalizes |
2600 | 2624 | * everything. |
2601 | 2625 | * |
2602 | | - * @return \type{\bool} true on success |
| 2626 | + * @return Bool true on success |
2603 | 2627 | */ |
2604 | 2628 | private function secureAndSplit() { |
2605 | 2629 | global $wgContLang, $wgLocalInterwiki; |
2606 | 2630 | |
2607 | 2631 | # Initialisation |
2608 | | - $rxTc = self::getTitleInvalidRegex(); |
2609 | | - |
2610 | 2632 | $this->mInterwiki = $this->mFragment = ''; |
2611 | 2633 | $this->mNamespace = $this->mDefaultNamespace; # Usually NS_MAIN |
2612 | 2634 | |
— | — | @@ -2620,7 +2642,6 @@ |
2621 | 2643 | # Note: use of the /u option on preg_replace here will cause |
2622 | 2644 | # input with invalid UTF-8 sequences to be nullified out in PHP 5.2.x, |
2623 | 2645 | # conveniently disabling them. |
2624 | | - # |
2625 | 2646 | $dbkey = preg_replace( '/[ _\xA0\x{1680}\x{180E}\x{2000}-\x{200A}\x{2028}\x{2029}\x{202F}\x{205F}\x{3000}]+/u', '_', $dbkey ); |
2626 | 2647 | $dbkey = trim( $dbkey, '_' ); |
2627 | 2648 | |
— | — | @@ -2657,9 +2678,11 @@ |
2658 | 2679 | # For Talk:X pages, check if X has a "namespace" prefix |
2659 | 2680 | if ( $ns == NS_TALK && preg_match( $prefixRegexp, $dbkey, $x ) ) { |
2660 | 2681 | if ( $wgContLang->getNsIndex( $x[1] ) ) { |
2661 | | - return false; # Disallow Talk:File:x type titles... |
| 2682 | + # Disallow Talk:File:x type titles... |
| 2683 | + return false; |
2662 | 2684 | } elseif ( Interwiki::isValidInterwiki( $x[1] ) ) { |
2663 | | - return false; # Disallow Talk:Interwiki:x type titles... |
| 2685 | + # Disallow Talk:Interwiki:x type titles... |
| 2686 | + return false; |
2664 | 2687 | } |
2665 | 2688 | } |
2666 | 2689 | } elseif ( Interwiki::isValidInterwiki( $p ) ) { |
— | — | @@ -2674,7 +2697,9 @@ |
2675 | 2698 | $this->mInterwiki = $wgContLang->lc( $p ); |
2676 | 2699 | |
2677 | 2700 | # 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 | + { |
2679 | 2704 | if ( $dbkey == '' ) { |
2680 | 2705 | # Can't have an empty self-link |
2681 | 2706 | return false; |
— | — | @@ -2699,13 +2724,12 @@ |
2700 | 2725 | } while ( true ); |
2701 | 2726 | |
2702 | 2727 | # We already know that some pages won't be in the database! |
2703 | | - # |
2704 | 2728 | if ( $this->mInterwiki != '' || NS_SPECIAL == $this->mNamespace ) { |
2705 | 2729 | $this->mArticleID = 0; |
2706 | 2730 | } |
2707 | 2731 | $fragment = strstr( $dbkey, '#' ); |
2708 | 2732 | if ( false !== $fragment ) { |
2709 | | - $this->setFragment( preg_replace( '/^#_*/', '#', $fragment ) ); |
| 2733 | + $this->setFragment( $fragment ); |
2710 | 2734 | $dbkey = substr( $dbkey, 0, strlen( $dbkey ) - strlen( $fragment ) ); |
2711 | 2735 | # remove whitespace again: prevents "Foo_bar_#" |
2712 | 2736 | # becoming "Foo_bar_" |
— | — | @@ -2713,79 +2737,65 @@ |
2714 | 2738 | } |
2715 | 2739 | |
2716 | 2740 | # Reject illegal characters. |
2717 | | - # |
| 2741 | + $rxTc = self::getTitleInvalidRegex(); |
2718 | 2742 | if ( preg_match( $rxTc, $dbkey ) ) { |
2719 | 2743 | return false; |
2720 | 2744 | } |
2721 | 2745 | |
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. |
2727 | 2749 | 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 ) == '/..' ) ) |
2735 | 2757 | { |
2736 | 2758 | return false; |
2737 | 2759 | } |
2738 | 2760 | |
2739 | | - /** |
2740 | | - * Magic tilde sequences? Nu-uh! |
2741 | | - */ |
| 2761 | + # Magic tilde sequences? Nu-uh! |
2742 | 2762 | if ( strpos( $dbkey, '~~~' ) !== false ) { |
2743 | 2763 | return false; |
2744 | 2764 | } |
2745 | 2765 | |
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]] |
2753 | 2770 | if ( ( $this->mNamespace != NS_SPECIAL && strlen( $dbkey ) > 255 ) || |
2754 | 2771 | strlen( $dbkey ) > 512 ) |
2755 | 2772 | { |
2756 | 2773 | return false; |
2757 | 2774 | } |
2758 | 2775 | |
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. |
2767 | 2779 | $this->mUserCaseDBKey = $dbkey; |
2768 | 2780 | if ( $this->mInterwiki == '' ) { |
2769 | 2781 | $dbkey = self::capitalize( $dbkey, $this->mNamespace ); |
2770 | 2782 | } |
2771 | 2783 | |
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 ) { |
2780 | 2787 | return false; |
2781 | 2788 | } |
| 2789 | + |
2782 | 2790 | // Allow IPv6 usernames to start with '::' by canonicalizing IPv6 titles. |
2783 | 2791 | // IP names are not allowed for accounts, and can only be referring to |
2784 | 2792 | // edits from the IP. Given '::' abbreviations and caps/lowercaps, |
2785 | 2793 | // there are numerous ways to present the same IP. Having sp:contribs scan |
2786 | 2794 | // them all is silly and having some show the edits and others not is |
2787 | 2795 | // 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 | + |
2790 | 2800 | // Any remaining initial :s are illegal. |
2791 | 2801 | if ( $dbkey !== '' && ':' == $dbkey { 0 } ) { |
2792 | 2802 | return false; |
— | — | @@ -2808,7 +2818,7 @@ |
2809 | 2819 | * Deprecated for public use, use Title::makeTitle() with fragment parameter. |
2810 | 2820 | * Still in active use privately. |
2811 | 2821 | * |
2812 | | - * @param $fragment \type{\string} text |
| 2822 | + * @param $fragment String text |
2813 | 2823 | */ |
2814 | 2824 | public function setFragment( $fragment ) { |
2815 | 2825 | $this->mFragment = str_replace( '_', ' ', substr( $fragment, 1 ) ); |
— | — | @@ -2821,7 +2831,7 @@ |
2822 | 2832 | /** |
2823 | 2833 | * Get a Title object associated with the talk page of this article |
2824 | 2834 | * |
2825 | | - * @return \type{Title} the object for the talk page |
| 2835 | + * @return Title the object for the talk page |
2826 | 2836 | */ |
2827 | 2837 | public function getTalkPage() { |
2828 | 2838 | return Title::makeTitle( MWNamespace::getTalk( $this->getNamespace() ), $this->getDBkey() ); |
— | — | @@ -2831,7 +2841,7 @@ |
2832 | 2842 | * Get a title object associated with the subject page of this |
2833 | 2843 | * talk page |
2834 | 2844 | * |
2835 | | - * @return \type{Title} the object for the subject page |
| 2845 | + * @return Title the object for the subject page |
2836 | 2846 | */ |
2837 | 2847 | public function getSubjectPage() { |
2838 | 2848 | // Is this the same title? |
— | — | @@ -2852,7 +2862,7 @@ |
2853 | 2863 | * @param $options Array: may be FOR UPDATE |
2854 | 2864 | * @param $table String: table name |
2855 | 2865 | * @param $prefix String: fields prefix |
2856 | | - * @return \type{\arrayof{Title}} the Title objects linking here |
| 2866 | + * @return Array of Title objects linking here |
2857 | 2867 | */ |
2858 | 2868 | public function getLinksTo( $options = array(), $table = 'pagelinks', $prefix = 'pl' ) { |
2859 | 2869 | $linkCache = LinkCache::singleton(); |
— | — | @@ -2877,13 +2887,13 @@ |
2878 | 2888 | $retVal = array(); |
2879 | 2889 | if ( $db->numRows( $res ) ) { |
2880 | 2890 | 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 ) { |
2882 | 2893 | $linkCache->addGoodLinkObj( $row->page_id, $titleObj, $row->page_len, $row->page_is_redirect, $row->page_latest ); |
2883 | 2894 | $retVal[] = $titleObj; |
2884 | 2895 | } |
2885 | 2896 | } |
2886 | 2897 | } |
2887 | | - $db->freeResult( $res ); |
2888 | 2898 | return $retVal; |
2889 | 2899 | } |
2890 | 2900 | |
— | — | @@ -2895,7 +2905,7 @@ |
2896 | 2906 | * On heavily-used templates it will max out the memory. |
2897 | 2907 | * |
2898 | 2908 | * @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 |
2900 | 2910 | */ |
2901 | 2911 | public function getTemplateLinksTo( $options = array() ) { |
2902 | 2912 | return $this->getLinksTo( $options, 'templatelinks', 'tl' ); |
— | — | @@ -2905,7 +2915,7 @@ |
2906 | 2916 | * Get an array of Title objects referring to non-existent articles linked from this page |
2907 | 2917 | * |
2908 | 2918 | * @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 |
2910 | 2920 | */ |
2911 | 2921 | public function getBrokenLinksFrom() { |
2912 | 2922 | if ( $this->getArticleId() == 0 ) { |
— | — | @@ -2942,7 +2952,7 @@ |
2943 | 2953 | * Get a list of URLs to purge from the Squid cache when this |
2944 | 2954 | * page changes |
2945 | 2955 | * |
2946 | | - * @return \type{\arrayof{\string}} the URLs |
| 2956 | + * @return Array of String the URLs |
2947 | 2957 | */ |
2948 | 2958 | public function getSquidURLs() { |
2949 | 2959 | global $wgContLang; |
— | — | @@ -2978,8 +2988,8 @@ |
2979 | 2989 | /** |
2980 | 2990 | * Move this page without authentication |
2981 | 2991 | * |
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 |
2984 | 2994 | */ |
2985 | 2995 | public function moveNoAuth( &$nt ) { |
2986 | 2996 | return $this->moveTo( $nt, false ); |
— | — | @@ -2989,11 +2999,11 @@ |
2990 | 3000 | * Check whether a given move operation would be valid. |
2991 | 3001 | * Returns true if ok, or a getUserPermissionsErrors()-like array otherwise |
2992 | 3002 | * |
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 |
2995 | 3005 | * 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 |
2998 | 3008 | */ |
2999 | 3009 | public function isValidMoveOperation( &$nt, $auth = true, $reason = '' ) { |
3000 | 3010 | global $wgUser; |
— | — | @@ -3025,28 +3035,13 @@ |
3026 | 3036 | } |
3027 | 3037 | if ( ( $this->getDBkey() == '' ) || |
3028 | 3038 | ( !$oldid ) || |
3029 | | - ( $nt->getDBkey() == '' ) ) { |
| 3039 | + ( $nt->getDBkey() == '' ) ) { |
3030 | 3040 | $errors[] = array( 'badarticleerror' ); |
3031 | 3041 | } |
3032 | 3042 | |
3033 | 3043 | // Image-specific checks |
3034 | 3044 | 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 ) ); |
3051 | 3046 | } |
3052 | 3047 | |
3053 | 3048 | if ( $nt->getNamespace() == NS_FILE && $this->getNamespace() != NS_FILE ) { |
— | — | @@ -3094,25 +3089,56 @@ |
3095 | 3090 | } |
3096 | 3091 | |
3097 | 3092 | /** |
| 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 | + /** |
3098 | 3125 | * Move a title to a new location |
3099 | 3126 | * |
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 |
3102 | 3129 | * 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. |
3105 | 3132 | * 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 |
3107 | 3134 | */ |
3108 | 3135 | public function moveTo( &$nt, $auth = true, $reason = '', $createRedirect = true ) { |
3109 | | - global $wgContLang, $wgEnableInterwikiTemplatesTracking, $wgGlobalDatabase; |
3110 | | - |
3111 | 3136 | $err = $this->isValidMoveOperation( $nt, $auth, $reason ); |
3112 | 3137 | if ( is_array( $err ) ) { |
3113 | 3138 | return $err; |
3114 | 3139 | } |
3115 | 3140 | |
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 |
3117 | 3143 | $dbw = wfGetDB( DB_MASTER ); |
3118 | 3144 | if ( $this->getNamespace() == NS_FILE ) { |
3119 | 3145 | $file = wfLocalFile( $this ); |
— | — | @@ -3127,43 +3153,39 @@ |
3128 | 3154 | $dbw->begin(); # If $file was a LocalFile, its transaction would have closed our own. |
3129 | 3155 | $pageid = $this->getArticleID( self::GAID_FOR_UPDATE ); |
3130 | 3156 | $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 ); |
3138 | 3158 | |
| 3159 | + // Do the actual move |
| 3160 | + $err = $this->moveToInternal( $nt, $reason, $createRedirect ); |
3139 | 3161 | if ( is_array( $err ) ) { |
3140 | 3162 | # @todo FIXME: What about the File we have already moved? |
3141 | 3163 | $dbw->rollback(); |
3142 | 3164 | return $err; |
3143 | 3165 | } |
| 3166 | + |
3144 | 3167 | $redirid = $this->getArticleID(); |
3145 | 3168 | |
3146 | 3169 | // Refresh the sortkey for this row. Be careful to avoid resetting |
3147 | 3170 | // cl_timestamp, which may disturb time-based lists on some sites. |
3148 | | - $prefix = $dbw->selectField( |
| 3171 | + $prefixes = $dbw->select( |
3149 | 3172 | 'categorylinks', |
3150 | | - 'cl_sortkey_prefix', |
| 3173 | + array( 'cl_sortkey_prefix', 'cl_to' ), |
3151 | 3174 | array( 'cl_from' => $pageid ), |
3152 | 3175 | __METHOD__ |
3153 | 3176 | ); |
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 | + ); |
3168 | 3190 | } |
3169 | 3191 | |
3170 | 3192 | if ( $protected ) { |
— | — | @@ -3229,20 +3251,19 @@ |
3230 | 3252 | $u->doUpdate(); |
3231 | 3253 | } |
3232 | 3254 | # Update message cache for interface messages |
3233 | | - if ( $nt->getNamespace() == NS_MEDIAWIKI ) { |
3234 | | - global $wgMessageCache; |
3235 | | - |
| 3255 | + if ( $this->getNamespace() == NS_MEDIAWIKI ) { |
3236 | 3256 | # @bug 17860: old article can be deleted, if this the case, |
3237 | 3257 | # delete it from message cache |
3238 | 3258 | if ( $this->getArticleID() === 0 ) { |
3239 | | - $wgMessageCache->replace( $this->getDBkey(), false ); |
| 3259 | + MessageCache::singleton()->replace( $this->getDBkey(), false ); |
3240 | 3260 | } else { |
3241 | 3261 | $oldarticle = new Article( $this ); |
3242 | | - $wgMessageCache->replace( $this->getDBkey(), $oldarticle->getContent() ); |
| 3262 | + MessageCache::singleton()->replace( $this->getDBkey(), $oldarticle->getContent() ); |
3243 | 3263 | } |
3244 | | - |
| 3264 | + } |
| 3265 | + if ( $nt->getNamespace() == NS_MEDIAWIKI ) { |
3245 | 3266 | $newarticle = new Article( $nt ); |
3246 | | - $wgMessageCache->replace( $nt->getDBkey(), $newarticle->getContent() ); |
| 3267 | + MessageCache::singleton()->replace( $nt->getDBkey(), $newarticle->getContent() ); |
3247 | 3268 | } |
3248 | 3269 | |
3249 | 3270 | global $wgUser; |
— | — | @@ -3251,78 +3272,80 @@ |
3252 | 3273 | } |
3253 | 3274 | |
3254 | 3275 | /** |
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 |
3257 | 3278 | * |
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 |
3263 | 3283 | */ |
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; |
3266 | 3286 | |
3267 | | - $comment = wfMsgForContent( '1movedto2_redir', $this->getPrefixedText(), $nt->getPrefixedText() ); |
| 3287 | + $moveOverRedirect = $nt->exists(); |
3268 | 3288 | |
| 3289 | + $commentMsg = ( $moveOverRedirect ? '1movedto2_redir' : '1movedto2' ); |
| 3290 | + $comment = wfMsgForContent( $commentMsg, $this->getPrefixedText(), $nt->getPrefixedText() ); |
| 3291 | + |
3269 | 3292 | if ( $reason ) { |
3270 | 3293 | $comment .= wfMsgForContent( 'colon-separator' ) . $reason; |
3271 | 3294 | } |
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 ); |
3274 | 3297 | |
3275 | | - $now = wfTimestampNow(); |
3276 | | - $newid = $nt->getArticleID(); |
3277 | 3298 | $oldid = $this->getArticleID(); |
3278 | 3299 | $latest = $this->getLatestRevID(); |
3279 | 3300 | |
| 3301 | + $oldns = $this->getNamespace(); |
| 3302 | + $olddbk = $this->getDBkey(); |
| 3303 | + |
3280 | 3304 | $dbw = wfGetDB( DB_MASTER ); |
3281 | 3305 | |
3282 | | - $rcts = $dbw->timestamp( $nt->getEarliestRevTime() ); |
3283 | | - $newns = $nt->getNamespace(); |
3284 | | - $newdbk = $nt->getDBkey(); |
| 3306 | + if ( $moveOverRedirect ) { |
| 3307 | + $rcts = $dbw->timestamp( $nt->getEarliestRevTime() ); |
3285 | 3308 | |
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__ ); |
3296 | 3331 | } |
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 | + ); |
3312 | 3337 | } |
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 | | - ); |
3318 | 3338 | |
3319 | 3339 | # Save a null revision in the page's history notifying of the move |
3320 | 3340 | $nullRevision = Revision::newNullRevision( $dbw, $oldid, $comment, true ); |
| 3341 | + if ( !is_object( $nullRevision ) ) { |
| 3342 | + throw new MWException( 'No valid null revision produced in ' . __METHOD__ ); |
| 3343 | + } |
3321 | 3344 | $nullRevId = $nullRevision->insertOn( $dbw ); |
3322 | 3345 | |
3323 | 3346 | # Change the name of the target page: |
3324 | 3347 | $dbw->update( 'page', |
3325 | 3348 | /* SET */ array( |
3326 | | - 'page_touched' => $dbw->timestamp( $now ), |
| 3349 | + 'page_touched' => $dbw->timestamp(), |
3327 | 3350 | 'page_namespace' => $nt->getNamespace(), |
3328 | 3351 | 'page_title' => $nt->getDBkey(), |
3329 | 3352 | 'page_latest' => $nullRevId, |
— | — | @@ -3361,110 +3384,34 @@ |
3362 | 3385 | __METHOD__ ); |
3363 | 3386 | $redirectSuppressed = false; |
3364 | 3387 | } 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 | + |
3365 | 3399 | $this->resetArticleID( 0 ); |
3366 | 3400 | $redirectSuppressed = true; |
3367 | 3401 | } |
3368 | 3402 | |
3369 | 3403 | # Log the move |
3370 | 3404 | $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 ) ); |
3372 | 3407 | |
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(); |
3455 | 3412 | } 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 ); |
3458 | 3415 | } |
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() |
3469 | 3416 | $this->purgeSquid(); |
3470 | 3417 | } |
3471 | 3418 | |
— | — | @@ -3474,10 +3421,11 @@ |
3475 | 3422 | * @param $nt Title Move target |
3476 | 3423 | * @param $auth bool Whether $wgUser's permissions should be checked |
3477 | 3424 | * @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 |
3480 | 3427 | * @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 |
3482 | 3430 | */ |
3483 | 3431 | public function moveSubpages( $nt, $auth = true, $reason = '', $createRedirect = true ) { |
3484 | 3432 | global $wgMaximumMovedPages; |
— | — | @@ -3544,7 +3492,7 @@ |
3545 | 3493 | * Checks if this page is just a one-rev redirect. |
3546 | 3494 | * Adds lock, so don't use just for light purposes. |
3547 | 3495 | * |
3548 | | - * @return \type{\bool} |
| 3496 | + * @return Bool |
3549 | 3497 | */ |
3550 | 3498 | public function isSingleRevRedirect() { |
3551 | 3499 | $dbw = wfGetDB( DB_MASTER ); |
— | — | @@ -3581,8 +3529,8 @@ |
3582 | 3530 | * Checks if $this can be moved to a given Title |
3583 | 3531 | * - Selects for update, so don't call it unless you mean business |
3584 | 3532 | * |
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 |
3587 | 3535 | */ |
3588 | 3536 | public function isValidMoveTarget( $nt ) { |
3589 | 3537 | # Is it an existing file? |
— | — | @@ -3623,7 +3571,7 @@ |
3624 | 3572 | /** |
3625 | 3573 | * Can this title be added to a user's watchlist? |
3626 | 3574 | * |
3627 | | - * @return \type{\bool} TRUE or FALSE |
| 3575 | + * @return Bool TRUE or FALSE |
3628 | 3576 | */ |
3629 | 3577 | public function isWatchable() { |
3630 | 3578 | return !$this->isExternal() && MWNamespace::isWatchable( $this->getNamespace() ); |
— | — | @@ -3633,31 +3581,35 @@ |
3634 | 3582 | * Get categories to which this Title belongs and return an array of |
3635 | 3583 | * categories' names. |
3636 | 3584 | * |
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 |
3639 | 3587 | */ |
3640 | 3588 | public function getParentCategories() { |
3641 | 3589 | global $wgContLang; |
3642 | 3590 | |
3643 | | - $titlekey = $this->getArticleId(); |
| 3591 | + $data = array(); |
| 3592 | + |
| 3593 | + $titleKey = $this->getArticleId(); |
| 3594 | + |
| 3595 | + if ( $titleKey === 0 ) { |
| 3596 | + return $data; |
| 3597 | + } |
| 3598 | + |
3644 | 3599 | $dbr = wfGetDB( DB_SLAVE ); |
3645 | | - $categorylinks = $dbr->tableName( 'categorylinks' ); |
3646 | 3600 | |
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 | + ); |
3652 | 3608 | |
3653 | | - $res = $dbr->query( $sql ); |
3654 | | - |
3655 | 3609 | if ( $dbr->numRows( $res ) > 0 ) { |
3656 | | - foreach ( $res as $row ) |
| 3610 | + foreach ( $res as $row ) { |
3657 | 3611 | // $data[] = Title::newFromText($wgContLang->getNSText ( NS_CATEGORY ).':'.$row->cl_to); |
3658 | 3612 | $data[$wgContLang->getNSText( NS_CATEGORY ) . ':' . $row->cl_to] = $this->getFullText(); |
3659 | | - $dbr->freeResult( $res ); |
3660 | | - } else { |
3661 | | - $data = array(); |
| 3613 | + } |
3662 | 3614 | } |
3663 | 3615 | return $data; |
3664 | 3616 | } |
— | — | @@ -3665,8 +3617,8 @@ |
3666 | 3618 | /** |
3667 | 3619 | * Get a tree of parent categories |
3668 | 3620 | * |
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 |
3671 | 3623 | */ |
3672 | 3624 | public function getParentCategoryTree( $children = array() ) { |
3673 | 3625 | $stack = array(); |
— | — | @@ -3684,18 +3636,16 @@ |
3685 | 3637 | } |
3686 | 3638 | } |
3687 | 3639 | } |
3688 | | - return $stack; |
3689 | | - } else { |
3690 | | - return array(); |
3691 | 3640 | } |
| 3641 | + |
| 3642 | + return $stack; |
3692 | 3643 | } |
3693 | 3644 | |
3694 | | - |
3695 | 3645 | /** |
3696 | 3646 | * Get an associative array for selecting this title from |
3697 | 3647 | * the "page" table |
3698 | 3648 | * |
3699 | | - * @return \type{\array} Selection array |
| 3649 | + * @return Array suitable for the $where parameter of DB::select() |
3700 | 3650 | */ |
3701 | 3651 | public function pageCond() { |
3702 | 3652 | if ( $this->mArticleID > 0 ) { |
— | — | @@ -3709,12 +3659,12 @@ |
3710 | 3660 | /** |
3711 | 3661 | * Get the revision ID of the previous revision |
3712 | 3662 | * |
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 |
3716 | 3666 | */ |
3717 | 3667 | 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 ); |
3719 | 3669 | return $db->selectField( 'revision', 'rev_id', |
3720 | 3670 | array( |
3721 | 3671 | 'rev_page' => $this->getArticleId( $flags ), |
— | — | @@ -3728,12 +3678,12 @@ |
3729 | 3679 | /** |
3730 | 3680 | * Get the revision ID of the next revision |
3731 | 3681 | * |
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 |
3735 | 3685 | */ |
3736 | 3686 | 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 ); |
3738 | 3688 | return $db->selectField( 'revision', 'rev_id', |
3739 | 3689 | array( |
3740 | 3690 | 'rev_page' => $this->getArticleId( $flags ), |
— | — | @@ -3747,28 +3697,37 @@ |
3748 | 3698 | /** |
3749 | 3699 | * Get the first revision of the page |
3750 | 3700 | * |
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 |
3753 | 3703 | */ |
3754 | 3704 | public function getFirstRevision( $flags = 0 ) { |
3755 | | - $db = ( $flags & GAID_FOR_UPDATE ) ? wfGetDB( DB_MASTER ) : wfGetDB( DB_SLAVE ); |
3756 | 3705 | $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 | + } |
3759 | 3716 | } |
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; |
3770 | 3718 | } |
3771 | 3719 | |
3772 | 3720 | /** |
| 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 | + /** |
3773 | 3732 | * Check if this is a new page |
3774 | 3733 | * |
3775 | 3734 | * @return bool |
— | — | @@ -3779,45 +3738,70 @@ |
3780 | 3739 | } |
3781 | 3740 | |
3782 | 3741 | /** |
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. |
3784 | 3744 | * |
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. |
3786 | 3748 | */ |
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 | + } |
3788 | 3759 | $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 | + ); |
3797 | 3768 | } |
3798 | 3769 | |
3799 | 3770 | /** |
3800 | | - * Get the number of revisions between the given revision IDs. |
| 3771 | + * Get the number of authors between the given revision IDs. |
3801 | 3772 | * Used for diffs and other things that really need it. |
3802 | 3773 | * |
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. |
3806 | 3778 | */ |
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 | + } |
3808 | 3789 | $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 |
3814 | 3797 | ); |
| 3798 | + return (int)$dbr->numRows( $res ); |
3815 | 3799 | } |
3816 | 3800 | |
3817 | 3801 | /** |
3818 | 3802 | * Compare with another title. |
3819 | 3803 | * |
3820 | | - * @param $title \type{Title} |
3821 | | - * @return \type{\bool} TRUE or FALSE |
| 3804 | + * @param $title Title |
| 3805 | + * @return Bool |
3822 | 3806 | */ |
3823 | 3807 | public function equals( Title $title ) { |
3824 | 3808 | // Note: === is necessary for proper matching of number-like titles. |
— | — | @@ -3828,7 +3812,10 @@ |
3829 | 3813 | |
3830 | 3814 | /** |
3831 | 3815 | * Callback for usort() to do title sorts by (namespace, title) |
3832 | | - * |
| 3816 | + * |
| 3817 | + * @param $a Title |
| 3818 | + * @param $b Title |
| 3819 | + * |
3833 | 3820 | * @return Integer: result of string comparison, or namespace comparison |
3834 | 3821 | */ |
3835 | 3822 | public static function compare( $a, $b ) { |
— | — | @@ -3842,7 +3829,7 @@ |
3843 | 3830 | /** |
3844 | 3831 | * Return a string representation of this title |
3845 | 3832 | * |
3846 | | - * @return \type{\string} String representation of this title |
| 3833 | + * @return String representation of this title |
3847 | 3834 | */ |
3848 | 3835 | public function __toString() { |
3849 | 3836 | return $this->getPrefixedText(); |
— | — | @@ -3855,7 +3842,7 @@ |
3856 | 3843 | * If you want to know if a title can be meaningfully viewed, you should |
3857 | 3844 | * probably call the isKnown() method instead. |
3858 | 3845 | * |
3859 | | - * @return \type{\bool} |
| 3846 | + * @return Bool |
3860 | 3847 | */ |
3861 | 3848 | public function exists() { |
3862 | 3849 | return $this->getArticleId() != 0; |
— | — | @@ -3875,28 +3862,28 @@ |
3876 | 3863 | * existing code, but we might want to add an optional parameter to skip |
3877 | 3864 | * it and any other expensive checks.) |
3878 | 3865 | * |
3879 | | - * @return \type{\bool} |
| 3866 | + * @return Bool |
3880 | 3867 | */ |
3881 | 3868 | public function isAlwaysKnown() { |
3882 | 3869 | if ( $this->mInterwiki != '' ) { |
3883 | 3870 | return true; // any interwiki link might be viewable, for all we know |
3884 | 3871 | } |
3885 | 3872 | 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; |
3901 | 3888 | } |
3902 | 3889 | } |
3903 | 3890 | |
— | — | @@ -3906,10 +3893,10 @@ |
3907 | 3894 | * links to the title should be rendered as "bluelinks" (as opposed to |
3908 | 3895 | * "redlinks" to non-existent pages). |
3909 | 3896 | * |
3910 | | - * @return \type{\bool} |
| 3897 | + * @return Bool |
3911 | 3898 | */ |
3912 | 3899 | public function isKnown() { |
3913 | | - return $this->exists() || $this->isAlwaysKnown(); |
| 3900 | + return $this->isAlwaysKnown() || $this->exists(); |
3914 | 3901 | } |
3915 | 3902 | |
3916 | 3903 | /** |
— | — | @@ -3925,20 +3912,38 @@ |
3926 | 3913 | if ( $this->mNamespace == NS_MEDIAWIKI ) { |
3927 | 3914 | // If the page doesn't exist but is a known system message, default |
3928 | 3915 | // 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; |
3934 | 3917 | } |
3935 | 3918 | |
3936 | 3919 | return false; |
3937 | 3920 | } |
3938 | 3921 | |
3939 | 3922 | /** |
| 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 | + /** |
3940 | 3945 | * Is this in a namespace that allows actual pages? |
3941 | 3946 | * |
3942 | | - * @return \type{\bool} |
| 3947 | + * @return Bool |
3943 | 3948 | * @internal note -- uses hardcoded namespace index instead of constants |
3944 | 3949 | */ |
3945 | 3950 | public function canExist() { |
— | — | @@ -3964,7 +3969,7 @@ |
3965 | 3970 | * Get the last touched timestamp |
3966 | 3971 | * |
3967 | 3972 | * @param $db DatabaseBase: optional db |
3968 | | - * @return \type{\string} Last touched timestamp |
| 3973 | + * @return String last-touched timestamp |
3969 | 3974 | */ |
3970 | 3975 | public function getTouched( $db = null ) { |
3971 | 3976 | $db = isset( $db ) ? $db : wfGetDB( DB_SLAVE ); |
— | — | @@ -3976,7 +3981,7 @@ |
3977 | 3982 | * Get the timestamp when this page was updated since the user last saw it. |
3978 | 3983 | * |
3979 | 3984 | * @param $user User |
3980 | | - * @return Mixed: string/null |
| 3985 | + * @return String|Null |
3981 | 3986 | */ |
3982 | 3987 | public function getNotificationTimestamp( $user = null ) { |
3983 | 3988 | global $wgUser, $wgShowUpdatedMarker; |
— | — | @@ -3986,7 +3991,8 @@ |
3987 | 3992 | } |
3988 | 3993 | // Check cache first |
3989 | 3994 | $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 ) ) { |
3991 | 3997 | return $this->mNotificationTimestamp[$uid]; |
3992 | 3998 | } |
3993 | 3999 | if ( !$uid || !$wgShowUpdatedMarker ) { |
— | — | @@ -4011,7 +4017,7 @@ |
4012 | 4018 | /** |
4013 | 4019 | * Get the trackback URL for this page |
4014 | 4020 | * |
4015 | | - * @return \type{\string} Trackback URL |
| 4021 | + * @return String Trackback URL |
4016 | 4022 | */ |
4017 | 4023 | public function trackbackURL() { |
4018 | 4024 | global $wgScriptPath, $wgServer, $wgScriptExtension; |
— | — | @@ -4023,7 +4029,7 @@ |
4024 | 4030 | /** |
4025 | 4031 | * Get the trackback RDF for this page |
4026 | 4032 | * |
4027 | | - * @return \type{\string} Trackback RDF |
| 4033 | + * @return String Trackback RDF |
4028 | 4034 | */ |
4029 | 4035 | public function trackbackRDF() { |
4030 | 4036 | $url = htmlspecialchars( $this->getFullURL() ); |
— | — | @@ -4037,8 +4043,8 @@ |
4038 | 4044 | // Spec: http://www.sixapart.com/pronet/docs/trackback_spec |
4039 | 4045 | return "<!-- |
4040 | 4046 | <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/\"> |
4043 | 4049 | <rdf:Description |
4044 | 4050 | rdf:about=\"$url\" |
4045 | 4051 | dc:identifier=\"$url\" |
— | — | @@ -4052,7 +4058,7 @@ |
4053 | 4059 | * Generate strings used for xml 'id' names in monobook tabs |
4054 | 4060 | * |
4055 | 4061 | * @param $prepend string defaults to 'nstab-' |
4056 | | - * @return \type{\string} XML 'id' name |
| 4062 | + * @return String XML 'id' name |
4057 | 4063 | */ |
4058 | 4064 | public function getNamespaceKey( $prepend = 'nstab-' ) { |
4059 | 4065 | global $wgContLang; |
— | — | @@ -4091,12 +4097,12 @@ |
4092 | 4098 | /** |
4093 | 4099 | * Returns true if this title resolves to the named special page |
4094 | 4100 | * |
4095 | | - * @param $name \type{\string} The special page name |
| 4101 | + * @param $name String The special page name |
4096 | 4102 | * @return boolean |
4097 | 4103 | */ |
4098 | 4104 | public function isSpecial( $name ) { |
4099 | 4105 | if ( $this->getNamespace() == NS_SPECIAL ) { |
4100 | | - list( $thisName, /* $subpage */ ) = SpecialPage::resolveAliasWithSubpage( $this->getDBkey() ); |
| 4106 | + list( $thisName, /* $subpage */ ) = SpecialPageFactory::resolveAlias( $this->getDBkey() ); |
4101 | 4107 | if ( $name == $thisName ) { |
4102 | 4108 | return true; |
4103 | 4109 | } |
— | — | @@ -4105,16 +4111,16 @@ |
4106 | 4112 | } |
4107 | 4113 | |
4108 | 4114 | /** |
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 |
4110 | 4117 | * |
4111 | | - * @return \type{Title} A new Title which points to the local default. |
4112 | | - * Otherwise, returns $this. |
| 4118 | + * @return Title |
4113 | 4119 | */ |
4114 | 4120 | public function fixSpecialName() { |
4115 | 4121 | if ( $this->getNamespace() == NS_SPECIAL ) { |
4116 | | - $canonicalName = SpecialPage::resolveAlias( $this->mDbkeyform ); |
| 4122 | + list( $canonicalName, /*...*/ ) = SpecialPageFactory::resolveAlias( $this->mDbkeyform ); |
4117 | 4123 | if ( $canonicalName ) { |
4118 | | - $localName = SpecialPage::getLocalNameFor( $canonicalName ); |
| 4124 | + $localName = SpecialPageFactory::getLocalNameFor( $canonicalName ); |
4119 | 4125 | if ( $localName != $this->mDbkeyform ) { |
4120 | 4126 | return Title::makeTitle( NS_SPECIAL, $localName ); |
4121 | 4127 | } |
— | — | @@ -4128,7 +4134,7 @@ |
4129 | 4135 | * In other words, is this a content page, for the purposes of calculating |
4130 | 4136 | * statistics, etc? |
4131 | 4137 | * |
4132 | | - * @return \type{\bool} |
| 4138 | + * @return Boolean |
4133 | 4139 | */ |
4134 | 4140 | public function isContentPage() { |
4135 | 4141 | return MWNamespace::isContent( $this->getNamespace() ); |
— | — | @@ -4137,9 +4143,8 @@ |
4138 | 4144 | /** |
4139 | 4145 | * Get all extant redirects to this Title |
4140 | 4146 | * |
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 |
4144 | 4149 | */ |
4145 | 4150 | public function getRedirectsHere( $ns = null ) { |
4146 | 4151 | $redirs = array(); |
— | — | @@ -4161,7 +4166,6 @@ |
4162 | 4167 | __METHOD__ |
4163 | 4168 | ); |
4164 | 4169 | |
4165 | | - |
4166 | 4170 | foreach ( $res as $row ) { |
4167 | 4171 | $redirs[] = self::newFromRow( $row ); |
4168 | 4172 | } |
— | — | @@ -4171,7 +4175,7 @@ |
4172 | 4176 | /** |
4173 | 4177 | * Check if this Title is a valid redirect target |
4174 | 4178 | * |
4175 | | - * @return \type{\bool} |
| 4179 | + * @return Bool |
4176 | 4180 | */ |
4177 | 4181 | public function isValidRedirectTarget() { |
4178 | 4182 | global $wgInvalidRedirectTargets; |
— | — | @@ -4203,8 +4207,7 @@ |
4204 | 4208 | } |
4205 | 4209 | |
4206 | 4210 | /** |
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. |
4209 | 4212 | * |
4210 | 4213 | * @return Boolean |
4211 | 4214 | */ |
— | — | @@ -4225,21 +4228,47 @@ |
4226 | 4229 | * @return array applicable restriction types |
4227 | 4230 | */ |
4228 | 4231 | public function getRestrictionTypes() { |
4229 | | - global $wgRestrictionTypes; |
4230 | | - $types = $this->exists() ? $wgRestrictionTypes : array( 'create' ); |
| 4232 | + if ( $this->getNamespace() == NS_SPECIAL ) { |
| 4233 | + return array(); |
| 4234 | + } |
4231 | 4235 | |
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' ) ); |
4234 | 4241 | } |
4235 | 4242 | |
4236 | 4243 | wfRunHooks( 'TitleGetRestrictionTypes', array( $this, &$types ) ); |
4237 | 4244 | |
| 4245 | + wfDebug( __METHOD__ . ': applicable restriction types for ' . |
| 4246 | + $this->getPrefixedText() . ' are ' . implode( ',', $types ) . "\n" ); |
| 4247 | + |
4238 | 4248 | return $types; |
4239 | 4249 | } |
| 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 | + } |
4240 | 4269 | |
4241 | 4270 | /** |
4242 | 4271 | * 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 |
4244 | 4273 | * binary sortkey that can be used for actual sorting. |
4245 | 4274 | * |
4246 | 4275 | * @param $prefix string The prefix to be used, specified using |
— | — | @@ -4256,10 +4285,12 @@ |
4257 | 4286 | // in order to re-sort existing category relations. |
4258 | 4287 | wfRunHooks( 'GetDefaultSortkey', array( $this, &$unprefixed ) ); |
4259 | 4288 | 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"; |
4264 | 4295 | } |
4265 | 4296 | return $unprefixed; |
4266 | 4297 | } |
— | — | @@ -4295,3 +4326,37 @@ |
4296 | 4327 | return wfGetLangObj( $pageLang ); |
4297 | 4328 | } |
4298 | 4329 | } |
| 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 |
4299 | 4364 | Reverse-merged /branches/iwtransclusion/phase3v2/includes/Title.php:r87108 |
4300 | 4365 | Reverse-merged /branches/iwtransclusion/phase3/includes/Title.php:r70764 |
Index: branches/iwtransclusion/phase3v3/languages/messages/MessagesEn.php |
— | — | @@ -1399,9 +1399,6 @@ |
1400 | 1400 | 'templatesused' => '{{PLURAL:$1|Template|Templates}} used on this page:', |
1401 | 1401 | 'templatesusedpreview' => '{{PLURAL:$1|Template|Templates}} used in this preview:', |
1402 | 1402 | '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:', |
1406 | 1403 | 'template-protected' => '(protected)', |
1407 | 1404 | 'template-semiprotected' => '(semi-protected)', |
1408 | 1405 | 'hiddencategories' => 'This page is a member of {{PLURAL:$1|1 hidden category|$1 hidden categories}}:', |