Index: trunk/phase3/maintenance/archives/patch-user_restrictions.sql |
— | — | @@ -0,0 +1,42 @@ |
| 2 | +-- Allows admins to block user from editing certain namespaces or pages |
| 3 | + |
| 4 | +CREATE TABLE /*$wgDBprefix*/user_restrictions ( |
| 5 | + -- ID of the restriction |
| 6 | + ur_id int NOT NULL auto_increment, |
| 7 | + |
| 8 | + -- Restriction type. Block from either editing namespace or page |
| 9 | + ur_type varbinary(255) NOT NULL, |
| 10 | + -- Namespace to restrict if ur_type = namespace |
| 11 | + ur_namespace int default NULL, |
| 12 | + -- Page to restrict if ur_type = page |
| 13 | + ur_page_namespace int default NULL, |
| 14 | + ur_page_title varchar(255) binary default '', |
| 15 | + |
| 16 | + -- User that is restricted |
| 17 | + ur_user int unsigned NOT NULL, |
| 18 | + ur_user_text tinyblob NOT NULL, |
| 19 | + |
| 20 | + -- User who has done this restriction |
| 21 | + ur_by int unsigned NOT NULL, |
| 22 | + ur_by_text varchar(255) binary NOT NULL default '', |
| 23 | + -- Reason for this restriction |
| 24 | + ur_reason tinyblob NOT NULL, |
| 25 | + |
| 26 | + -- Time when this restriction was made |
| 27 | + ur_timestamp varbinary(14) NOT NULL default '', |
| 28 | + -- Expiry or "infinity" |
| 29 | + ur_expiry varbinary(14) NOT NULL default '', |
| 30 | + |
| 31 | + PRIMARY KEY ur_id (ur_id), |
| 32 | + -- For looking up restrictions for user and title |
| 33 | + INDEX ur_user (ur_user,ur_user_text(255)), |
| 34 | + INDEX ur_user_page(ur_user,ur_page_namespace,ur_page_title(255)), |
| 35 | + INDEX ur_user_namespace(ur_user,ur_namespace), |
| 36 | + -- For Special:ListUserRestrictions |
| 37 | + INDEX ur_type (ur_type(255),ur_timestamp), |
| 38 | + INDEX ur_namespace (ur_namespace,ur_timestamp), |
| 39 | + INDEX ur_page (ur_page_namespace,ur_page_title,ur_timestamp), |
| 40 | + INDEX ur_timestamp (ur_timestamp), |
| 41 | + -- For quick removal of expired restrictions |
| 42 | + INDEX ur_expiry (ur_expiry) |
| 43 | +) /*$wgDBTableOptions*/; |
Property changes on: trunk/phase3/maintenance/archives/patch-user_restrictions.sql |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 44 | + native |
Index: trunk/phase3/maintenance/parserTests.inc |
— | — | @@ -593,7 +593,7 @@ |
594 | 594 | 'site_stats', 'hitcounter', 'ipblocks', 'image', 'oldimage', |
595 | 595 | 'recentchanges', 'watchlist', 'math', 'interwiki', |
596 | 596 | 'querycache', 'objectcache', 'job', 'redirect', 'querycachetwo', |
597 | | - 'archive', 'user_groups', 'page_props', 'category' |
| 597 | + 'archive', 'user_groups', 'page_props', 'category', 'user_restrictions', |
598 | 598 | ); |
599 | 599 | |
600 | 600 | if ($wgDBtype === 'mysql') |
Index: trunk/phase3/maintenance/updaters.inc |
— | — | @@ -145,9 +145,10 @@ |
146 | 146 | array( 'update_password_format' ), |
147 | 147 | |
148 | 148 | // 1.14 |
149 | | - array( 'add_field', 'site_stats', 'ss_active_users', 'patch-ss_active_users.sql' ), |
| 149 | + array( 'add_field', 'site_stats', 'ss_active_users', 'patch-ss_active_users.sql' ), |
150 | 150 | array( 'do_active_users_init' ), |
151 | | - array( 'add_field', 'ipblocks', 'ipb_allow_usertalk', 'patch-ipb_allow_usertalk.sql' ) |
| 151 | + array( 'add_field', 'ipblocks', 'ipb_allow_usertalk', 'patch-ipb_allow_usertalk.sql' ), |
| 152 | + array( 'add_table', 'user_restrictions', 'patch-user_restrictions.sql' ), |
152 | 153 | ); |
153 | 154 | |
154 | 155 | |
Index: trunk/phase3/maintenance/language/messages.inc |
— | — | @@ -569,6 +569,10 @@ |
570 | 570 | 'edit-conflict', |
571 | 571 | 'edit-no-change', |
572 | 572 | 'edit-already-exists', |
| 573 | + 'userrestricted-page', |
| 574 | + 'userrestricted-namespace', |
| 575 | + 'userrestricted-page-indef', |
| 576 | + 'userrestricted-namespace-indef', |
573 | 577 | ), |
574 | 578 | 'parserwarnings' => array( |
575 | 579 | 'expensive-parserfunction-warning', |
— | — | @@ -1804,6 +1808,7 @@ |
1805 | 1809 | 'ipbsubmit', |
1806 | 1810 | 'ipbother', |
1807 | 1811 | 'ipboptions', |
| 1812 | + 'ipbinfinite', |
1808 | 1813 | 'ipbotheroption', |
1809 | 1814 | 'ipbotherreason', |
1810 | 1815 | 'ipbhidename', |
— | — | @@ -1877,6 +1882,69 @@ |
1878 | 1883 | 'sorbs_create_account_reason', |
1879 | 1884 | 'cant-block-while-blocked', |
1880 | 1885 | ), |
| 1886 | + 'listuserrestrictions' => array( |
| 1887 | + 'listuserrestrictions', |
| 1888 | + 'listuserrestrictions-intro', |
| 1889 | + 'listuserrestrictions-row-ns', |
| 1890 | + 'listuserrestrictions-row-page', |
| 1891 | + 'listuserrestrictions-row-expiry', |
| 1892 | + 'listuserrestrictions-legend', |
| 1893 | + 'listuserrestrictions-type', |
| 1894 | + 'listuserrestrictions-user', |
| 1895 | + 'listuserrestrictions-namespace', |
| 1896 | + 'listuserrestrictions-page', |
| 1897 | + 'listuserrestrictions-submit', |
| 1898 | + 'listuserrestrictions-notfound', |
| 1899 | + 'listuserrestrictions-empty', |
| 1900 | + 'listuserrestrictions-remove', |
| 1901 | + 'userrestrictiontype-none', |
| 1902 | + 'userrestrictiontype-namespace', |
| 1903 | + 'userrestrictiontype-page', |
| 1904 | + ), |
| 1905 | + 'removerestrictions' => array( |
| 1906 | + 'removerestrictions', |
| 1907 | + 'removerestrictions-intro', |
| 1908 | + 'removerestrictions-noid', |
| 1909 | + 'removerestrictions-wrongid', |
| 1910 | + 'removerestrictions-legend', |
| 1911 | + 'removerestrictions-user', |
| 1912 | + 'removerestrictions-type', |
| 1913 | + 'removerestrictions-page', |
| 1914 | + 'removerestrictions-namespace', |
| 1915 | + 'removerestrictions-reason', |
| 1916 | + 'removerestrictions-submit', |
| 1917 | + 'removerestrictions-success', |
| 1918 | + ), |
| 1919 | + 'restrictuser' => array( |
| 1920 | + 'restrictuser', |
| 1921 | + 'restrictuser-userselect', |
| 1922 | + 'restrictuser-user', |
| 1923 | + 'restrictuser-go', |
| 1924 | + 'restrictuser-notfound', |
| 1925 | + 'restrictuser-existing', |
| 1926 | + 'restrictuser-legend-page', |
| 1927 | + 'restrictuser-legend-namespace', |
| 1928 | + 'restrictuser-title', |
| 1929 | + 'restrictuser-namespace', |
| 1930 | + 'restrictuser-expiry', |
| 1931 | + 'restrictuser-reason', |
| 1932 | + 'restrictuser-submit', |
| 1933 | + 'restrictuser-badtitle', |
| 1934 | + 'restrictuser-badnamespace', |
| 1935 | + 'restrictuser-badexpiry', |
| 1936 | + 'restrictuser-duptitle', |
| 1937 | + 'restrictuser-dupnamespace', |
| 1938 | + 'restrictuser-success', |
| 1939 | + 'restrictuser-description', |
| 1940 | + ), |
| 1941 | + 'restrictlog' => array( |
| 1942 | + 'restrictionlog', |
| 1943 | + 'restrictionlogtext', |
| 1944 | + 'restrictentry', |
| 1945 | + 'restrictremoveentry', |
| 1946 | + 'restrictlognamespace', |
| 1947 | + 'restrictlogpage', |
| 1948 | + ), |
1881 | 1949 | 'developertools' => array( |
1882 | 1950 | 'lockdb', |
1883 | 1951 | 'unlockdb', |
— | — | @@ -3005,6 +3073,10 @@ |
3006 | 3074 | 'sp-contributions' => '', |
3007 | 3075 | 'whatlinkshere' => 'What links here', |
3008 | 3076 | 'block' => 'Block/unblock', |
| 3077 | + 'listuserrestrictions' => 'Special:ListUserRestrictions', |
| 3078 | + 'removerestrictions' => 'Special:RemoveRestrictions', |
| 3079 | + 'restrictuser' => 'Restrict user', |
| 3080 | + 'restrictlog' => 'Special:Log/restrict', |
3009 | 3081 | 'developertools' => 'Developer tools', |
3010 | 3082 | 'movepage' => 'Move page', |
3011 | 3083 | 'export' => 'Export', |
Index: trunk/phase3/maintenance/tables.sql |
— | — | @@ -1243,4 +1243,47 @@ |
1244 | 1244 | PRIMARY KEY (ul_key) |
1245 | 1245 | ) /*$wgDBTableOptions*/; |
1246 | 1246 | |
| 1247 | +-- Allows admins to block user from editing certain namespaces or pages |
| 1248 | +CREATE TABLE /*$wgDBprefix*/user_restrictions ( |
| 1249 | + -- ID of the restriction |
| 1250 | + ur_id int NOT NULL auto_increment, |
| 1251 | + |
| 1252 | + -- Restriction type. Block from either editing namespace or page |
| 1253 | + ur_type varbinary(255) NOT NULL, |
| 1254 | + -- Namespace to restrict if ur_type = namespace |
| 1255 | + ur_namespace int default NULL, |
| 1256 | + -- Page to restrict if ur_type = page |
| 1257 | + ur_page_namespace int default NULL, |
| 1258 | + ur_page_title varchar(255) binary default '', |
| 1259 | + |
| 1260 | + -- User that is restricted |
| 1261 | + ur_user int unsigned NOT NULL, |
| 1262 | + ur_user_text tinyblob NOT NULL, |
| 1263 | + |
| 1264 | + -- User who has done this restriction |
| 1265 | + ur_by int unsigned NOT NULL, |
| 1266 | + ur_by_text varchar(255) binary NOT NULL default '', |
| 1267 | + -- Reason for this restriction |
| 1268 | + ur_reason tinyblob NOT NULL, |
| 1269 | + |
| 1270 | + -- Time when this restriction was made |
| 1271 | + ur_timestamp varbinary(14) NOT NULL default '', |
| 1272 | + -- Expiry or "infinity" |
| 1273 | + ur_expiry varbinary(14) NOT NULL default '', |
| 1274 | + |
| 1275 | + PRIMARY KEY ur_id (ur_id), |
| 1276 | + -- For looking up restrictions for user and title |
| 1277 | + INDEX ur_user (ur_user,ur_user_text(255)), |
| 1278 | + INDEX ur_user_page(ur_user,ur_page_namespace,ur_page_title(255)), |
| 1279 | + INDEX ur_user_namespace(ur_user,ur_namespace), |
| 1280 | + -- For Special:ListUserRestrictions |
| 1281 | + INDEX ur_type (ur_type(255),ur_timestamp), |
| 1282 | + INDEX ur_namespace (ur_namespace,ur_timestamp), |
| 1283 | + INDEX ur_page (ur_page_namespace,ur_page_title,ur_timestamp), |
| 1284 | + INDEX ur_timestamp (ur_timestamp), |
| 1285 | + -- For quick removal of expired restrictions |
| 1286 | + INDEX ur_expiry (ur_expiry) |
| 1287 | +) /*$wgDBTableOptions*/; |
| 1288 | + |
| 1289 | + |
1247 | 1290 | -- vim: sw=2 sts=2 et |
Index: trunk/phase3/includes/User.php |
— | — | @@ -151,7 +151,7 @@ |
152 | 152 | 'markbotedits', |
153 | 153 | 'minoredit', |
154 | 154 | 'move', |
155 | | - 'movepage', |
| 155 | + 'movefile', |
156 | 156 | 'move-rootuserpages', |
157 | 157 | 'move-subpages', |
158 | 158 | 'nominornewtalk', |
— | — | @@ -161,6 +161,7 @@ |
162 | 162 | 'proxyunbannable', |
163 | 163 | 'purge', |
164 | 164 | 'read', |
| 165 | + 'restrict', |
165 | 166 | 'reupload', |
166 | 167 | 'reupload-shared', |
167 | 168 | 'rollback', |
Index: trunk/phase3/includes/Article.php |
— | — | @@ -2435,7 +2435,12 @@ |
2436 | 2436 | ); |
2437 | 2437 | |
2438 | 2438 | # Delete restrictions for it |
2439 | | - $dbw->delete( 'page_restrictions', array ( 'pr_page' => $id ), __METHOD__ ); |
| 2439 | + $dbw->delete( 'page_restrictions', array( 'pr_page' => $id ), __METHOD__ ); |
| 2440 | + $dbw->delete( 'user_restrictions', |
| 2441 | + array( |
| 2442 | + 'ur_page_namespace' => $this->mTitle->getNamespace(), |
| 2443 | + 'ur_page_title' => $this->mTitle->getDBKey() |
| 2444 | + ), __METHOD__ ); |
2440 | 2445 | |
2441 | 2446 | # Now that it's safely backed up, delete it |
2442 | 2447 | $dbw->delete( 'page', array( 'page_id' => $id ), __METHOD__); |
Index: trunk/phase3/includes/UserRestriction.php |
— | — | @@ -0,0 +1,189 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * Object that represents a user restriction |
| 6 | + */ |
| 7 | +class UserRestriction { |
| 8 | + const PAGE = 'page'; |
| 9 | + const NAMESPACE = 'namespace'; |
| 10 | + |
| 11 | + private $mId, $mType, $mNamespace, $mPage, $mSubjectText, $mSubjectId, |
| 12 | + $mBlockerId, $mBlockerText, $mReason, $mTimestamp, $mExpiry; |
| 13 | + |
| 14 | + public static function newFromRow( $row ) { |
| 15 | + if( !$row ) |
| 16 | + return null; |
| 17 | + |
| 18 | + $obj = new UserRestriction(); |
| 19 | + $obj->mId = $row->ur_id; |
| 20 | + $obj->mType = $row->ur_type; |
| 21 | + if( $obj->mType == self::PAGE ) { |
| 22 | + $obj->mPage = Title::makeTitle( $row->ur_page_namespace, $row->ur_page_title ); |
| 23 | + } elseif( $obj->mType == self::NAMESPACE ) { |
| 24 | + $obj->mNamespace = $row->ur_namespace; |
| 25 | + } else { |
| 26 | + throw new MWException( "Unknown user restriction type: {$row->ur_type}" ); |
| 27 | + } |
| 28 | + |
| 29 | + $obj->mSubjectId = $row->ur_user; |
| 30 | + $obj->mSubjectText = $row->ur_user_text; |
| 31 | + $obj->mBlockerId = $row->ur_by; |
| 32 | + $obj->mBlockerText = $row->ur_by_text; |
| 33 | + $obj->mReason = $row->ur_reason; |
| 34 | + $obj->mTimestamp = wfTimestamp( TS_MW, $row->ur_timestamp ); |
| 35 | + $obj->mExpiry = $row->ur_expiry; |
| 36 | + return $obj; |
| 37 | + } |
| 38 | + |
| 39 | + public static function fetchForUser( $user, $forWrite = false ) { |
| 40 | + $dbr = wfGetDB( $forWrite ? DB_MASTER : DB_SLAVE ); |
| 41 | + if( is_int( $user ) ) |
| 42 | + $query = array( 'ur_user' => $user ); |
| 43 | + else |
| 44 | + $query = array( 'ur_user_text' => $user ); |
| 45 | + $res = $dbr->select( 'user_restrictions', '*', $query, __METHOD__ ); |
| 46 | + $result = array(); |
| 47 | + foreach( $res as $row ) { |
| 48 | + $result[] = self::newFromRow( $row ); |
| 49 | + } |
| 50 | + return $result; |
| 51 | + } |
| 52 | + |
| 53 | + public static function fetchForTitle( $user, $title ) { |
| 54 | + $dbr = wfGetDB( DB_SLAVE ); |
| 55 | + if( $user->isLoggedIn() ) |
| 56 | + $query = array( 'ur_user' => $user->getId() ); |
| 57 | + else |
| 58 | + $query = array( 'ur_user_text' => $user->getName() ); |
| 59 | + $query['ur_page_namespace'] = $title->getNamespace(); |
| 60 | + $query['ur_page_title'] = $title->getDBKey(); |
| 61 | + $res = $dbr->select( 'user_restrictions', '*', $query, __METHOD__ ); |
| 62 | + $result = array(); |
| 63 | + foreach( $res as $row ) { |
| 64 | + $result[] = self::newFromRow( $row ); |
| 65 | + } |
| 66 | + return $result; |
| 67 | + } |
| 68 | + |
| 69 | + public static function fetchForNamespace( $user, $ns ) { |
| 70 | + $dbr = wfGetDB( DB_SLAVE ); |
| 71 | + if( $user->isLoggedIn() ) |
| 72 | + $query = array( 'ur_user' => $user->getId() ); |
| 73 | + else |
| 74 | + $query = array( 'ur_user_text' => $user->getName() ); |
| 75 | + $query['ur_namespace'] = $ns; |
| 76 | + $res = $dbr->select( 'user_restrictions', '*', $query, __METHOD__ ); |
| 77 | + $result = array(); |
| 78 | + foreach( $res as $row ) { |
| 79 | + $result[] = self::newFromRow( $row ); |
| 80 | + } |
| 81 | + return $result; |
| 82 | + } |
| 83 | + |
| 84 | + public static function newFromId( $id, $forWrite = false ) { |
| 85 | + $dbr = wfGetDB( $forWrite ? DB_MASTER : DB_SLAVE ); |
| 86 | + if( !$id || !is_numeric( $id ) ) |
| 87 | + return null; |
| 88 | + $res = $dbr->selectRow( 'user_restrictions', '*', array( 'ur_id' => $id ), __METHOD__ ); |
| 89 | + return self::newFromRow( $res ); |
| 90 | + } |
| 91 | + |
| 92 | + public function getId() { return $this->mId; } |
| 93 | + public function setId( $v ) { $this->mId = $v; } |
| 94 | + public function getType() { return $this->mType; } |
| 95 | + public function setType( $v ) { $this->mType = $v; } |
| 96 | + public function getNamespace() { return $this->mNamespace; } |
| 97 | + public function setNamespace( $v ) { $this->mNamespace = $v; } |
| 98 | + public function getPage() { return $this->mPage; } |
| 99 | + public function setPage( $v ) { $this->mPage = $v; } |
| 100 | + public function getSubjectId() { return $this->mSubjectId; } |
| 101 | + public function setSubjectId( $v ) { $this->mSubjectId = $v; } |
| 102 | + public function getSubjectText() { return $this->mSubjectText; } |
| 103 | + public function setSubjectText( $v ) { $this->mSubjectText = $v; } |
| 104 | + public function getBlockerId() { return $this->mBlockerId; } |
| 105 | + public function setBlockerId( $v ) { $this->mBlockerId = $v; } |
| 106 | + public function getBlockerText() { return $this->mBlockerText; } |
| 107 | + public function setBlockerText( $v ) { $this->mBlockerText = $v; } |
| 108 | + public function getReason() { return $this->mReason; } |
| 109 | + public function setReason( $v ) { $this->mReason = $v; } |
| 110 | + public function getTimestamp() { return $this->mTimestamp; } |
| 111 | + public function setTimestamp( $v ) { $this->mTimestamp = $v; } |
| 112 | + public function getExpiry() { return $this->mExpiry; } |
| 113 | + public function setExpiry( $v ) { $this->mExpiry = $v; } |
| 114 | + |
| 115 | + public function isPage() { |
| 116 | + return $this->mType == self::PAGE; |
| 117 | + } |
| 118 | + public function isNamespace() { |
| 119 | + return $this->mType == self::NAMESPACE; |
| 120 | + } |
| 121 | + |
| 122 | + public function isExpired() { |
| 123 | + return is_numeric( $this->mExpiry ) && $this->mExpiry < wfTimestampNow( TS_MW ); |
| 124 | + } |
| 125 | + |
| 126 | + public function deleteIfExpired() { |
| 127 | + if( $this->isExpired() ) { |
| 128 | + $this->delete(); |
| 129 | + return true; |
| 130 | + } else { |
| 131 | + return false; |
| 132 | + } |
| 133 | + } |
| 134 | + |
| 135 | + public function delete() { |
| 136 | + $dbw = wfGetDB( DB_MASTER ); |
| 137 | + $dbw->delete( 'user_restrictions', array( 'ur_id' => $this->mId ), __METHOD__ ); |
| 138 | + return $dbw->affectedRows(); |
| 139 | + } |
| 140 | + |
| 141 | + public static function purgeExpired() { |
| 142 | + $dbw = wfGetDB( DB_MASTER ); |
| 143 | + $dbw->delete( 'user_restrictions', array( 'ur_expiry < ' . $dbw->addQuotes( $dbw->timestamp() ) ), __METHOD__ ); |
| 144 | + } |
| 145 | + |
| 146 | + public function commit() { |
| 147 | + $dbw = wfGetDB( DB_MASTER ); |
| 148 | + $this->setId( $dbw->nextSequenceValue('user_restrictions_ur_id_val') ); |
| 149 | + $row = array( |
| 150 | + 'ur_id' => $this->mId, |
| 151 | + 'ur_type' => $this->mType, |
| 152 | + 'ur_user' => $this->mSubjectId, |
| 153 | + 'ur_user_text' => $this->mSubjectText, |
| 154 | + 'ur_by' => $this->mBlockerId, |
| 155 | + 'ur_by_text' => $this->mBlockerText, |
| 156 | + 'ur_reason' => $this->mReason, |
| 157 | + 'ur_timestamp' => $dbw->timestamp( $this->mTimestamp ), |
| 158 | + 'ur_expiry' => $this->mExpiry, |
| 159 | + ); |
| 160 | + if( $this->isPage() ) { |
| 161 | + $row['ur_page_namespace'] = $this->mPage->getNamespace(); |
| 162 | + $row['ur_page_title'] = $this->mPage->getDbKey(); |
| 163 | + } |
| 164 | + if( $this->isNamespace() ) { |
| 165 | + $row['ur_namespace'] = $this->mNamespace; |
| 166 | + } |
| 167 | + $dbw->insert( 'user_restrictions', $row, __METHOD__ ); |
| 168 | + } |
| 169 | + |
| 170 | + public static function formatType( $type ) { |
| 171 | + return wfMsg( 'userrestrictiontype-' . $type ); |
| 172 | + } |
| 173 | + |
| 174 | + /** |
| 175 | + * Converts expiry which user input to the internal representation. |
| 176 | + * Returns false if invalid expiry is set, Block::infinity() on empty value, |
| 177 | + * Block::infinity() on infinity or 14-symbol timestamp |
| 178 | + */ |
| 179 | + public static function convertExpiry( $expiry ) { |
| 180 | + if( !$expiry ) |
| 181 | + return Block::infinity(); |
| 182 | + if( in_array( $expiry, array( 'infinite', 'infinity', 'indefinite' ) ) ) |
| 183 | + return Block::infinity(); |
| 184 | + $unix = @strtotime( $expiry ); |
| 185 | + if( !$unix || $unix === -1 ) |
| 186 | + return false; |
| 187 | + else |
| 188 | + return wfTimestamp( TS_MW, $unix ); |
| 189 | + } |
| 190 | +} |
Property changes on: trunk/phase3/includes/UserRestriction.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 191 | + native |
Index: trunk/phase3/includes/AutoLoader.php |
— | — | @@ -201,6 +201,8 @@ |
202 | 202 | 'UserArray' => 'includes/UserArray.php', |
203 | 203 | 'UserArrayFromResult' => 'includes/UserArray.php', |
204 | 204 | 'UserMailer' => 'includes/UserMailer.php', |
| 205 | + 'UserRestriction' => 'includes/UserRestriction.php', |
| 206 | + 'UserRestrictionsPager' => 'includes/specials/SpecialListUserRestrictions.php', |
205 | 207 | 'UserRightsProxy' => 'includes/UserRightsProxy.php', |
206 | 208 | 'WatchedItem' => 'includes/WatchedItem.php', |
207 | 209 | 'WatchlistEditor' => 'includes/WatchlistEditor.php', |
Index: trunk/phase3/includes/Title.php |
— | — | @@ -1009,9 +1009,7 @@ |
1010 | 1010 | } |
1011 | 1011 | $errors = $this->getUserPermissionsErrorsInternal( $action, $user, $doExpensiveQueries ); |
1012 | 1012 | |
1013 | | - global $wgContLang; |
1014 | | - global $wgLang; |
1015 | | - global $wgEmailConfirmToEdit; |
| 1013 | + global $wgContLang, $wgLang, $wgEmailConfirmToEdit; |
1016 | 1014 | |
1017 | 1015 | if ( $wgEmailConfirmToEdit && !$user->isEmailConfirmed() && $action != 'createaccount' ) { |
1018 | 1016 | $errors[] = array( 'confirmedittext' ); |
— | — | @@ -1043,20 +1041,7 @@ |
1044 | 1042 | $blockTimestamp = $wgLang->timeanddate( wfTimestamp( TS_MW, $user->mBlock->mTimestamp ), true ); |
1045 | 1043 | |
1046 | 1044 | if ( $blockExpiry == 'infinity' ) { |
1047 | | - // Entry in database (table ipblocks) is 'infinity' but 'ipboptions' uses 'infinite' or 'indefinite' |
1048 | | - $scBlockExpiryOptions = wfMsg( 'ipboptions' ); |
1049 | | - |
1050 | | - foreach ( explode( ',', $scBlockExpiryOptions ) as $option ) { |
1051 | | - if ( strpos( $option, ':' ) == false ) |
1052 | | - continue; |
1053 | | - |
1054 | | - list ($show, $value) = explode( ":", $option ); |
1055 | | - |
1056 | | - if ( $value == 'infinite' || $value == 'indefinite' ) { |
1057 | | - $blockExpiry = $show; |
1058 | | - break; |
1059 | | - } |
1060 | | - } |
| 1045 | + $blockExpiry = wfMsg( 'ipbinfinite' ); |
1061 | 1046 | } else { |
1062 | 1047 | $blockExpiry = $wgLang->timeanddate( wfTimestamp( TS_MW, $blockExpiry ), true ); |
1063 | 1048 | } |
— | — | @@ -1066,9 +1051,9 @@ |
1067 | 1052 | $errors[] = array( ($block->mAuto ? 'autoblockedtext' : 'blockedtext'), $link, $reason, $ip, $name, |
1068 | 1053 | $blockid, $blockExpiry, $intended, $blockTimestamp ); |
1069 | 1054 | } |
1070 | | - |
| 1055 | + |
1071 | 1056 | // Remove the errors being ignored. |
1072 | | - |
| 1057 | + |
1073 | 1058 | foreach( $errors as $index => $error ) { |
1074 | 1059 | $error_key = is_array($error) ? $error[0] : $error; |
1075 | 1060 | |
— | — | @@ -1091,6 +1076,8 @@ |
1092 | 1077 | * @return \type{\array} Array of arrays of the arguments to wfMsg to explain permissions problems. |
1093 | 1078 | */ |
1094 | 1079 | private function getUserPermissionsErrorsInternal( $action, $user, $doExpensiveQueries = true ) { |
| 1080 | + global $wgLang; |
| 1081 | + |
1095 | 1082 | wfProfileIn( __METHOD__ ); |
1096 | 1083 | |
1097 | 1084 | $errors = array(); |
— | — | @@ -1262,6 +1249,34 @@ |
1263 | 1250 | $errors[] = $return; |
1264 | 1251 | } |
1265 | 1252 | |
| 1253 | + // Check per-user restrictions |
| 1254 | + if( $doExpensiveQueries && $action != 'read' ) { |
| 1255 | + $rs = UserRestriction::fetchForTitle( $user, $this ); |
| 1256 | + if( !$rs ) |
| 1257 | + $rs = UserRestriction::fetchForNamespace( $user, $this->getNamespace() ); |
| 1258 | + if( $rs ) { |
| 1259 | + $r = $rs[0]; |
| 1260 | + if( !$r->deleteIfExpired() ) { |
| 1261 | + $error = array(); |
| 1262 | + $start = array( $wgLang->date( $r->getTimestamp() ), $wgLang->time( $r->getTimestamp() ) ); |
| 1263 | + if( $r->isPage() ) |
| 1264 | + $error = array( 'userrestricted-page', $this->getFullText(), |
| 1265 | + $r->getBlockerText(), $r->getReason(), $start[0], $start[1] ); |
| 1266 | + elseif( $r->isNamespace() ) |
| 1267 | + $error = array( 'userrestricted-namespace', $wgLang->getDisplayNsText( $this->getNamespace() ), |
| 1268 | + $r->getBlockerText(), $r->getReason(), $start[0], $start[1] ); |
| 1269 | + |
| 1270 | + if( $r->getExpiry() == 'infinity' ) { |
| 1271 | + $error[0] .= '-indef'; |
| 1272 | + } else { |
| 1273 | + $error[] = $wgLang->date( $r->getExpiry() ); |
| 1274 | + $error[] = $wgLang->time( $r->getExpiry() ); |
| 1275 | + } |
| 1276 | + $errors[] = $error; |
| 1277 | + } |
| 1278 | + } |
| 1279 | + } |
| 1280 | + |
1266 | 1281 | wfProfileOut( __METHOD__ ); |
1267 | 1282 | return $errors; |
1268 | 1283 | } |
— | — | @@ -2558,6 +2573,12 @@ |
2559 | 2574 | $log->addEntry( 'move_prot', $nt, $comment, array($this->getPrefixedText()) ); // FIXME: $params? |
2560 | 2575 | } |
2561 | 2576 | |
| 2577 | + # Update user restrictions |
| 2578 | + $dbw->update( 'user_restrictions', |
| 2579 | + array( 'ur_page_namespace' => $nt->getNamespace(), 'ur_page_title' => $nt->getDBKey() ), |
| 2580 | + array( 'ur_page_namespace' => $this->getNamespace(), 'ur_page_title' => $this->getDBKey() ), |
| 2581 | + __METHOD__ ); |
| 2582 | + |
2562 | 2583 | # Update watchlists |
2563 | 2584 | $oldnamespace = $this->getNamespace() & ~1; |
2564 | 2585 | $newnamespace = $nt->getNamespace() & ~1; |
Index: trunk/phase3/includes/DefaultSettings.php |
— | — | @@ -1232,6 +1232,7 @@ |
1233 | 1233 | $wgGroupPermissions['sysop']['apihighlimits'] = true; |
1234 | 1234 | $wgGroupPermissions['sysop']['browsearchive'] = true; |
1235 | 1235 | $wgGroupPermissions['sysop']['noratelimit'] = true; |
| 1236 | +$wgGroupPermissions['sysop']['restrict'] = true; |
1236 | 1237 | $wgGroupPermissions['sysop']['movefile'] = true; |
1237 | 1238 | #$wgGroupPermissions['sysop']['mergehistory'] = true; |
1238 | 1239 | |
— | — | @@ -2798,6 +2799,7 @@ |
2799 | 2800 | 'patrol', |
2800 | 2801 | 'merge', |
2801 | 2802 | 'suppress', |
| 2803 | + 'restrict', |
2802 | 2804 | ); |
2803 | 2805 | |
2804 | 2806 | /** |
— | — | @@ -2853,6 +2855,7 @@ |
2854 | 2856 | 'patrol' => 'patrol-log-page', |
2855 | 2857 | 'merge' => 'mergelog', |
2856 | 2858 | 'suppress' => 'suppressionlog', |
| 2859 | + 'restrict' => 'restrictionlog', |
2857 | 2860 | ); |
2858 | 2861 | |
2859 | 2862 | /** |
— | — | @@ -2874,6 +2877,7 @@ |
2875 | 2878 | 'patrol' => 'patrol-log-header', |
2876 | 2879 | 'merge' => 'mergelogpagetext', |
2877 | 2880 | 'suppress' => 'suppressionlogtext', |
| 2881 | + 'restrict' => 'restrictionlogtext', |
2878 | 2882 | ); |
2879 | 2883 | |
2880 | 2884 | /** |
— | — | @@ -2913,6 +2917,8 @@ |
2914 | 2918 | 'suppress/delete' => 'suppressedarticle', |
2915 | 2919 | 'suppress/block' => 'blocklogentry', |
2916 | 2920 | 'suppress/reblock' => 'reblock-logentry', |
| 2921 | + 'restrict/restrict' => 'restrictentry', |
| 2922 | + 'restrict/remove' => 'restrictremoveentry', |
2917 | 2923 | ); |
2918 | 2924 | |
2919 | 2925 | /** |
— | — | @@ -2984,6 +2990,8 @@ |
2985 | 2991 | 'Preferences' => 'users', |
2986 | 2992 | 'Resetpass' => 'users', |
2987 | 2993 | 'DeletedContributions' => 'users', |
| 2994 | + 'ListUserRestrictions' => 'users', |
| 2995 | + 'RestrictUser' => 'users', |
2988 | 2996 | |
2989 | 2997 | 'Mostlinked' => 'highuse', |
2990 | 2998 | 'Mostlinkedcategories' => 'highuse', |
Index: trunk/phase3/includes/specials/SpecialRestrictUser.php |
— | — | @@ -2,6 +2,8 @@ |
3 | 3 | |
4 | 4 | function wfSpecialRestrictUser( $par = null ) { |
5 | 5 | global $wgOut, $wgRequest; |
| 6 | + $wgOut->addHTML( wfMsgExt( 'restrictuser-description', 'parse' ) ); |
| 7 | + |
6 | 8 | $user = $userOrig = null; |
7 | 9 | if( $par ) { |
8 | 10 | $userOrig = $par; |
— | — | @@ -48,8 +50,6 @@ |
49 | 51 | } |
50 | 52 | |
51 | 53 | public static function existingRestrictions( $restrictions ) { |
52 | | - //TODO: autoload? |
53 | | - require_once( dirname( __FILE__ ) . '/SpecialListUserRestrictions.php' ); |
54 | 54 | $s = Xml::fieldset( wfMsg( 'restrictuser-existing' ) ) . '<ul>'; |
55 | 55 | foreach( $restrictions as $r ) |
56 | 56 | $s .= UserRestrictionsPager::formatRestriction( $r ); |
— | — | @@ -126,6 +126,7 @@ |
127 | 127 | $l = new LogPage( 'restrict' ); |
128 | 128 | $l->addEntry( 'restrict', Title::makeTitle( NS_USER, $user ), $r->getReason(), |
129 | 129 | array( $r->getType(), $r->getPage()->getFullText(), $logExpiry) ); |
| 130 | + self::invalidateCache( $user ); |
130 | 131 | } |
131 | 132 | |
132 | 133 | public static function namespaceRestrictionForm( $uid, $user, $oldRestrictions ) { |
— | — | @@ -136,13 +137,13 @@ |
137 | 138 | $wgUser->matchEditToken( $wgRequest->getVal( 'edittoken' ) ) ) { |
138 | 139 | $ns = $wgRequest->getVal( 'namespace' ); |
139 | 140 | if( $wgContLang->getNsText( $ns ) === false ) |
140 | | - $error = wfMsgExt( 'restrictuser-badnamespace', 'parseinline' ); |
| 141 | + $error = array( 'restrictuser-badnamespace' ); |
141 | 142 | elseif( UserRestriction::convertExpiry( $wgRequest->getVal( 'expiry' ) ) === false ) |
142 | | - $error = wfMsgExt( 'restrictuser-badexpiry', 'parseinline', $wgRequest->getVal( 'expiry' ) ); |
| 143 | + $error = array( 'restrictuser-badexpiry', $wgRequest->getVal( 'expiry' ) ); |
143 | 144 | else |
144 | 145 | foreach( $oldRestrictions as $r ) |
145 | 146 | if( $r->isNamespace() && $r->getNamespace() == $ns ) |
146 | | - $error = wfMsgExt( 'restrictuser-dupnamespace', 'parse' ); |
| 147 | + $error = array( 'restrictuser-dupnamespace' ); |
147 | 148 | if( !$error ) { |
148 | 149 | self::doNamespaceRestriction( $uid, $user ); |
149 | 150 | $success = array('restrictuser-success', $user); |
— | — | @@ -185,5 +186,11 @@ |
186 | 187 | $l = new LogPage( 'restrict' ); |
187 | 188 | $l->addEntry( 'restrict', Title::makeTitle( NS_USER, $user ), $r->getReason(), |
188 | 189 | array( $r->getType(), $r->getNamespace(), $logExpiry ) ); |
| 190 | + self::invalidateCache( $user ); |
189 | 191 | } |
| 192 | + |
| 193 | + private static function invalidateCache( $user ) { |
| 194 | + $userObj = User::newFromName( $user, false ); |
| 195 | + $userObj->invalidateCache(); |
| 196 | + } |
190 | 197 | } |
Index: trunk/phase3/includes/specials/SpecialRemoveRestrictions.php |
— | — | @@ -56,5 +56,7 @@ |
57 | 57 | if( $r->isNamespace() ) |
58 | 58 | $params[] = $r->getNamespace(); |
59 | 59 | $log->addEntry( 'remove', Title::makeTitle( NS_USER, $r->getSubjectText() ), $reason, $params ); |
| 60 | + $userObj = User::newFromName( $r->getSubjectText(), false ); |
| 61 | + $userObj->invalidateCache(); |
60 | 62 | return $result; |
61 | 63 | } |
Index: trunk/phase3/includes/specials/SpecialListUserRestrictions.php |
— | — | @@ -134,7 +134,7 @@ |
135 | 135 | $subjlink = $sk->userLink( $r->getSubjectId(), $r->getSubjectText() ) . |
136 | 136 | $sk->userToolLinks( $r->getSubjectId(), $r->getSubjectText() ); |
137 | 137 | $expiry = is_numeric( $r->getExpiry() ) ? |
138 | | - wfMsg( 'listuserrestrictions-row-expiry', $wgLang->timeanddate( $r->getExpiry() ) ) : |
| 138 | + wfMsg( 'listuserrestrictions-row-expiry', $wgLang->date( $r->getExpiry() ), $wgLang->time( $r->getExpiry() ) ) : |
139 | 139 | wfMsg( 'ipbinfinite' ); |
140 | 140 | $msg = ''; |
141 | 141 | if( $r->isNamespace() ) { |
Index: trunk/phase3/includes/SpecialPage.php |
— | — | @@ -129,6 +129,9 @@ |
130 | 130 | 'Allpages' => 'SpecialAllpages', |
131 | 131 | 'Prefixindex' => 'SpecialPrefixindex', |
132 | 132 | 'Ipblocklist' => array( 'SpecialPage', 'Ipblocklist' ), |
| 133 | + 'ListUserRestrictions' => array( 'SpecialPage', 'ListUserRestrictions' ), |
| 134 | + 'RemoveRestrictions' => array( 'UnlistedSpecialPage', 'RemoveRestrictions', 'restrict' ), |
| 135 | + 'RestrictUser' => array( 'SpecialPage', 'RestrictUser', 'restrict' ), |
133 | 136 | 'Specialpages' => array( 'UnlistedSpecialPage', 'Specialpages' ), |
134 | 137 | 'Contributions' => 'SpecialContributions', |
135 | 138 | 'Emailuser' => array( 'UnlistedSpecialPage', 'Emailuser' ), |
Index: trunk/phase3/includes/LogPage.php |
— | — | @@ -193,6 +193,19 @@ |
194 | 194 | } else { |
195 | 195 | $rv = wfMsgForContent( $wgLogActions[$key], $titleLink ); |
196 | 196 | } |
| 197 | + } elseif( $type == 'restrict' ) { |
| 198 | + if( $params[0] == UserRestriction::PAGE ) |
| 199 | + $subj = wfMsgExt( 'restrictlogpage', 'parseinline', $params[1] ); |
| 200 | + if( $params[0] == UserRestriction::NAMESPACE ) |
| 201 | + $subj = wfMsgExt( 'restrictlognamespace', 'parseinline', $wgLang->getDisplayNsText( $params[1] ) ); |
| 202 | + $expiry = ''; |
| 203 | + if( $key == 'restrict/restrict' ) |
| 204 | + $expiry = $wgLang->translateBlockExpiry( $params[2] ); |
| 205 | + if ( $skin ) { |
| 206 | + $rv = wfMsg( $wgLogActions[$key], $titleLink, $subj, $expiry ); |
| 207 | + } else { |
| 208 | + $rv = wfMsgForContent( $wgLogActions[$key], $titleLink, $subj, $expiry ); |
| 209 | + } |
197 | 210 | } else { |
198 | 211 | $details = ''; |
199 | 212 | array_unshift( $params, $titleLink ); |
— | — | @@ -264,6 +277,7 @@ |
265 | 278 | } |
266 | 279 | break; |
267 | 280 | case 'rights': |
| 281 | + case 'restrict': |
268 | 282 | $text = $wgContLang->ucfirst( $title->getText() ); |
269 | 283 | $titleLink = $skin->makeLinkObj( Title::makeTitle( NS_USER, $text ) ); |
270 | 284 | break; |
Index: trunk/phase3/languages/messages/MessagesEn.php |
— | — | @@ -431,6 +431,9 @@ |
432 | 432 | 'LinkSearch' => array( 'LinkSearch' ), |
433 | 433 | 'DeletedContributions' => array( 'DeletedContributions' ), |
434 | 434 | 'Interwiki' => array( 'Interwiki' ), |
| 435 | + 'ListUserRestrictions' => array( 'ListUserRestrictions' ), |
| 436 | + 'RemoveRestrictions' => array( 'RemoveRestrictions' ), |
| 437 | + 'RestrictUser' => array( 'RestrictUser' ), |
435 | 438 | ); |
436 | 439 | |
437 | 440 | /** |
— | — | @@ -1196,7 +1199,39 @@ |
1197 | 1200 | 'edit-no-change' => 'Your edit was ignored, because no change was made to the text.', |
1198 | 1201 | 'edit-already-exists' => 'Could not create a new page. |
1199 | 1202 | It already exists.', |
| 1203 | +'userrestricted-page' => '<big>\'\'\'Your user name or IP address has been restricted from editing page "$1".\'\'\'</big> |
1200 | 1204 | |
| 1205 | +The restriction was put by [[User:$2|$2]]. |
| 1206 | +The reason given is \'\'$3\'\'. |
| 1207 | + |
| 1208 | +Restriction was put on $4 at $5 and expires on $6 at $7. |
| 1209 | + |
| 1210 | +You can contact [[User:$2|$2]] or another [[{{MediaWiki:Grouppage-sysop}}|administrator]] to discuss the restriction.', |
| 1211 | +'userrestricted-namespace' => "<big>'''Your user name or IP address has been restricted from editing $1 namespace.'''</big> |
| 1212 | + |
| 1213 | +The restriction was put by [[User:$2|$2]]. |
| 1214 | +The reason given is ''$3''. |
| 1215 | + |
| 1216 | +Restriction was put on $4 at $5 and expires on $6 at $7. |
| 1217 | + |
| 1218 | +You can contact [[User:$2|$2]] or another [[{{MediaWiki:Grouppage-sysop}}|administrator]] to discuss the restriction.", |
| 1219 | +'userrestricted-page-indef' => '<big>\'\'\'Your user name or IP address has been restricted from editing page "$1".\'\'\'</big> |
| 1220 | + |
| 1221 | +The restriction was put by [[User:$2|$2]]. |
| 1222 | +The reason given is \'\'$3\'\'. |
| 1223 | + |
| 1224 | +Restriction was put on $4 at $5 and will not expire. |
| 1225 | + |
| 1226 | +You can contact [[User:$2|$2]] or another [[{{MediaWiki:Grouppage-sysop}}|administrator]] to discuss the restriction.', |
| 1227 | +'userrestricted-namespace-indef' => "<big>'''Your user name or IP address has been restricted from editing $1 namespace.'''</big> |
| 1228 | + |
| 1229 | +The restriction was put by [[User:$2|$2]]. |
| 1230 | +The reason given is ''$3''. |
| 1231 | + |
| 1232 | +Restriction was put on $4 at $5 and will not expire. |
| 1233 | + |
| 1234 | +You can contact [[User:$2|$2]] or another [[{{MediaWiki:Grouppage-sysop}}|administrator]] to discuss the restriction.", |
| 1235 | + |
1201 | 1236 | # Parser/template warnings |
1202 | 1237 | 'expensive-parserfunction-warning' => 'Warning: This page contains too many expensive parser function calls. |
1203 | 1238 | |
— | — | @@ -2604,6 +2639,7 @@ |
2605 | 2640 | 'ipbsubmit' => 'Block this user', |
2606 | 2641 | 'ipbother' => 'Other time:', |
2607 | 2642 | 'ipboptions' => '2 hours:2 hours,1 day:1 day,3 days:3 days,1 week:1 week,2 weeks:2 weeks,1 month:1 month,3 months:3 months,6 months:6 months,1 year:1 year,infinite:infinite', # display1:time1,display2:time2,... |
| 2643 | +'ipbinfinite' => 'infinite', |
2608 | 2644 | 'ipbotheroption' => 'other', |
2609 | 2645 | 'ipbotherreason' => 'Other/additional reason:', |
2610 | 2646 | 'ipbhidename' => 'Hide username from the block log, active block list and user list', |
— | — | @@ -2686,6 +2722,72 @@ |
2687 | 2723 | You cannot create an account', |
2688 | 2724 | 'cant-block-while-blocked' => 'You cannot block other users while you are blocked.', |
2689 | 2725 | |
| 2726 | +# Special:ListUserRestrictions |
| 2727 | +'listuserrestrictions' => 'List of user restrictions', |
| 2728 | +'listuserrestrictions-intro' => 'This list contains all restrictions from editing certain pages and namespaces put on users. |
| 2729 | +[[Special:Ipblocklist|Blocks]] are not listed here.', |
| 2730 | +'listuserrestrictions-row-ns' => 'restricted $1 from editing $2 namespace ($3)', |
| 2731 | +'listuserrestrictions-row-page' => 'restricted $1 from editing $2 ($3)', |
| 2732 | +'listuserrestrictions-row-expiry' => 'expires on $1 at $2', |
| 2733 | +'listuserrestrictions-legend' => 'Find a restriction', |
| 2734 | +'listuserrestrictions-type' => 'Type:', |
| 2735 | +'listuserrestrictions-user' => 'User:', |
| 2736 | +'listuserrestrictions-namespace' => 'Namespace:', |
| 2737 | +'listuserrestrictions-page' => 'Page:', |
| 2738 | +'listuserrestrictions-submit' => 'Go', |
| 2739 | +'listuserrestrictions-notfound' => 'There is no restriction that matches specified criteria.', |
| 2740 | +'listuserrestrictions-empty' => 'This list is empty.', |
| 2741 | +'listuserrestrictions-remove' => 'remove', |
| 2742 | +'userrestrictiontype-none' => '(none)', |
| 2743 | +'userrestrictiontype-namespace' => 'Namespace', |
| 2744 | +'userrestrictiontype-page' => 'Page', |
| 2745 | + |
| 2746 | +# Special:RemoveRestrictions |
| 2747 | +'removerestrictions' => 'Remove restriction from a user', |
| 2748 | +'removerestrictions-intro' => 'Use the form below to remove a restriction from a certain user.', |
| 2749 | +'removerestrictions-noid' => 'No restriction ID was specified.', |
| 2750 | +'removerestrictions-wrongid' => 'Restriction with that ID not found. |
| 2751 | +Most probably someone has removed it or it expired.', |
| 2752 | +'removerestrictions-legend' => 'Remove a restriction', |
| 2753 | +'removerestrictions-user' => 'Restricted user:', |
| 2754 | +'removerestrictions-type' => 'Restriction type:', |
| 2755 | +'removerestrictions-page' => 'Page:', |
| 2756 | +'removerestrictions-namespace' => 'Namespace:', |
| 2757 | +'removerestrictions-reason' => 'Reason:', |
| 2758 | +'removerestrictions-submit' => 'Remove the restriction', |
| 2759 | +'removerestrictions-success' => 'Successfully removed the restriction from [[User:$1|$1]].', |
| 2760 | + |
| 2761 | +# Restrict user |
| 2762 | +'restrictuser' => 'Restrict user', |
| 2763 | +'restrictuser-userselect' => 'Select a user', |
| 2764 | +'restrictuser-user' => 'User:', |
| 2765 | +'restrictuser-go' => 'Restrict user', |
| 2766 | +'restrictuser-notfound' => 'User not found', |
| 2767 | +'restrictuser-existing' => 'Existing restrictions', |
| 2768 | +'restrictuser-legend-page' => 'Restrict from editing certain page', |
| 2769 | +'restrictuser-legend-namespace' => 'Restrict from editing certain namespace', |
| 2770 | +'restrictuser-title' => 'Page to restrict:', |
| 2771 | +'restrictuser-namespace' => 'Namespace:', |
| 2772 | +'restrictuser-expiry' => 'Expires:', |
| 2773 | +'restrictuser-reason' => 'Reason:', |
| 2774 | +'restrictuser-submit' => 'Restrict user', |
| 2775 | +'restrictuser-badtitle' => 'Invalid title specified: $1.', |
| 2776 | +'restrictuser-badnamespace' => 'Invalid namespace specified.', |
| 2777 | +'restrictuser-badexpiry' => 'Invalid expiry specified: $1.', |
| 2778 | +'restrictuser-duptitle' => 'User is already restricted from editing this title.', |
| 2779 | +'restrictuser-dupnamespace' => 'User is already restricted from editing this namespace.', |
| 2780 | +'restrictuser-success' => 'Successfully restricted user $1.', |
| 2781 | +'restrictuser-description' => 'Use the form below to block write access to a specific page or namespace from a specific IP address or username. |
| 2782 | +This should be done only in accordance with policy. Fill in a specific reason below.', |
| 2783 | + |
| 2784 | +# Special:Log/restrict |
| 2785 | +'restrictionlog' => 'User restriction log', |
| 2786 | +'restrictionlogtext' => 'This log contains all restrictions put on users by administrators.', |
| 2787 | +'restrictentry' => 'restricted $1 from editing $2 (expiry set to $3)', |
| 2788 | +'restrictremoveentry' => 'removed restriction from $1 for editing $2', |
| 2789 | +'restrictlognamespace' => '$1 namespace', |
| 2790 | +'restrictlogpage' => '[[$1]]', # do not translate or duplicate this message to other languages |
| 2791 | + |
2690 | 2792 | # Developer tools |
2691 | 2793 | 'lockdb' => 'Lock database', |
2692 | 2794 | 'unlockdb' => 'Unlock database', |