Index: trunk/phase3/maintenance/protect.php |
— | — | @@ -28,8 +28,9 @@ |
29 | 29 | $this->mDescription = "Protect or unprotect an article from the command line."; |
30 | 30 | $this->addOption( 'unprotect', 'Removes protection' ); |
31 | 31 | $this->addOption( 'semiprotect', 'Adds semi-protection' ); |
32 | | - $this->addOption( 'u', 'Username to protect with', false, true ); |
33 | | - $this->addOption( 'r', 'Reason for un/protection', false, true ); |
| 32 | + $this->addOption( 'cascade', 'Add cascading protection' ); |
| 33 | + $this->addOption( 'user', 'Username to protect with', false, true, 'u' ); |
| 34 | + $this->addOption( 'reason', 'Reason for un/protection', false, true, 'r' ); |
34 | 35 | $this->addArg( 'title', 'Title to protect', true ); |
35 | 36 | } |
36 | 37 | |
— | — | @@ -39,6 +40,8 @@ |
40 | 41 | $userName = $this->getOption( 'u', 'Maintenance script' ); |
41 | 42 | $reason = $this->getOption( 'r', '' ); |
42 | 43 | |
| 44 | + $cascade = $this->hasOption( 'cascade' ); |
| 45 | + |
43 | 46 | $protection = "sysop"; |
44 | 47 | if ( $this->hasOption( 'semiprotect' ) ) { |
45 | 48 | $protection = "autoconfirmed"; |
— | — | @@ -46,11 +49,11 @@ |
47 | 50 | $protection = ""; |
48 | 51 | } |
49 | 52 | |
50 | | - $wgUser = User::newFromName( $userName ); |
51 | | - if ( !$wgUser ) { |
| 53 | + $user = User::newFromName( $userName ); |
| 54 | + if ( !$user ) { |
52 | 55 | $this->error( "Invalid username", true ); |
53 | 56 | } |
54 | | - |
| 57 | + |
55 | 58 | $restrictions = array( 'edit' => $protection, 'move' => $protection ); |
56 | 59 | |
57 | 60 | $t = Title::newFromText( $this->getArg() ); |
— | — | @@ -58,12 +61,18 @@ |
59 | 62 | $this->error( "Invalid title", true ); |
60 | 63 | } |
61 | 64 | |
62 | | - $article = new Article( $t ); |
| 65 | + $restrictions = array(); |
| 66 | + foreach( $t->getRestrictionTypes() as $type ) { |
| 67 | + $restrictions[$type] = $protection; |
| 68 | + } |
63 | 69 | |
64 | 70 | # un/protect the article |
65 | 71 | $this->output( "Updating protection status... " ); |
66 | | - $success = $article->updateRestrictions( $restrictions, $reason ); |
67 | | - if ( $success ) { |
| 72 | + |
| 73 | + $page = WikiPage::factory( $t ); |
| 74 | + $status = $page->doUpdateRestrictions( $restrictions, array(), $cascade, $reason, $user ); |
| 75 | + |
| 76 | + if ( $status->isOK() ) { |
68 | 77 | $this->output( "done\n" ); |
69 | 78 | } else { |
70 | 79 | $this->output( "failed\n" ); |
Index: trunk/phase3/maintenance/importImages.php |
— | — | @@ -231,44 +231,44 @@ |
232 | 232 | } |
233 | 233 | } |
234 | 234 | |
235 | | - $doProtect = false; |
236 | | - $restrictions = array(); |
| 235 | + if ( isset( $options['dry'] ) ) { |
| 236 | + echo( "done.\n" ); |
| 237 | + } elseif ( $image->recordUpload( $archive->value, $commentText, $license ) ) { |
| 238 | + # We're done! |
| 239 | + echo( "done.\n" ); |
237 | 240 | |
238 | | - global $wgRestrictionLevels; |
| 241 | + $doProtect = false; |
239 | 242 | |
240 | | - $protectLevel = isset( $options['protect'] ) ? $options['protect'] : null; |
| 243 | + global $wgRestrictionLevels; |
241 | 244 | |
242 | | - if ( $protectLevel && in_array( $protectLevel, $wgRestrictionLevels ) ) { |
243 | | - $restrictions['move'] = $protectLevel; |
244 | | - $restrictions['edit'] = $protectLevel; |
| 245 | + $protectLevel = isset( $options['protect'] ) ? $options['protect'] : null; |
| 246 | + |
| 247 | + if ( $protectLevel && in_array( $protectLevel, $wgRestrictionLevels ) ) { |
245 | 248 | $doProtect = true; |
246 | | - } |
247 | | - if ( isset( $options['unprotect'] ) ) { |
248 | | - $restrictions['move'] = ''; |
249 | | - $restrictions['edit'] = ''; |
| 249 | + } |
| 250 | + if ( isset( $options['unprotect'] ) ) { |
| 251 | + $protectLevel = ''; |
250 | 252 | $doProtect = true; |
251 | | - } |
| 253 | + } |
252 | 254 | |
253 | | - |
254 | | - if ( isset( $options['dry'] ) ) { |
255 | | - echo( "done.\n" ); |
256 | | - } elseif ( $image->recordUpload( $archive->value, $commentText, $license ) ) { |
257 | | - # We're done! |
258 | | - echo( "done.\n" ); |
259 | 255 | if ( $doProtect ) { |
260 | 256 | # Protect the file |
261 | | - $article = new Article( $title ); |
262 | 257 | echo "\nWaiting for slaves...\n"; |
263 | 258 | // Wait for slaves. |
264 | 259 | sleep( 2.0 ); # Why this sleep? |
265 | 260 | wfWaitForSlaves(); |
266 | 261 | |
267 | 262 | echo( "\nSetting image restrictions ... " ); |
268 | | - if ( $article->updateRestrictions( $restrictions ) ) { |
269 | | - echo( "done.\n" ); |
270 | | - } else { |
271 | | - echo( "failed.\n" ); |
| 263 | + |
| 264 | + $cascade = false; |
| 265 | + $restrictions = array(); |
| 266 | + foreach( $title->getRestrictionTypes() as $type ) { |
| 267 | + $restrictions[$type] = $protectLevel; |
272 | 268 | } |
| 269 | + |
| 270 | + $page = WikiPage::factory( $title ); |
| 271 | + $status = $page->doUpdateRestrictions( $restrictions, array(), $cascade, '', $user ); |
| 272 | + echo( ( $status->isOK() ? 'done' : 'failed' ) . "\n" ); |
273 | 273 | } |
274 | 274 | |
275 | 275 | } else { |
Index: trunk/phase3/includes/Article.php |
— | — | @@ -1784,7 +1784,19 @@ |
1785 | 1785 | |
1786 | 1786 | /** |
1787 | 1787 | * @param $limit array |
| 1788 | + * @param $expiry array |
| 1789 | + * @param $cascade bool |
1788 | 1790 | * @param $reason string |
| 1791 | + * @param $user User |
| 1792 | + * @return Status |
| 1793 | + */ |
| 1794 | + public function doUpdateRestrictions( array $limit, array $expiry, &$cascade, $reason, User $user ) { |
| 1795 | + return $this->mPage->doUpdateRestrictions( $limit, $expiry, $cascade, $reason, $user ); |
| 1796 | + } |
| 1797 | + |
| 1798 | + /** |
| 1799 | + * @param $limit array |
| 1800 | + * @param $reason string |
1789 | 1801 | * @param $cascade int |
1790 | 1802 | * @param $expiry array |
1791 | 1803 | * @return bool |
Index: trunk/phase3/includes/api/ApiProtect.php |
— | — | @@ -106,17 +106,13 @@ |
107 | 107 | $watch = $params['watch'] ? 'watch' : $params['watchlist']; |
108 | 108 | $this->setWatch( $watch, $titleObj ); |
109 | 109 | |
110 | | - if ( $titleObj->exists() ) { |
111 | | - $pageObj = WikiPage::factory( $titleObj ); |
112 | | - $ok = $pageObj->updateRestrictions( $protections, $params['reason'], $cascade, $expiryarray ); |
113 | | - } else { |
114 | | - $ok = $titleObj->updateTitleProtection( $protections['create'], $params['reason'], $expiryarray['create'] ); |
| 110 | + $pageObj = WikiPage::factory( $titleObj ); |
| 111 | + $status = $pageObj->doUpdateRestrictions( $protections, $expiryarray, $cascade, $params['reason'], $this->getUser() ); |
| 112 | + |
| 113 | + if ( !$status->isOK() ) { |
| 114 | + $errors = $status->getErrorsArray(); |
| 115 | + $this->dieUsageMsg( $errors[0] ); |
115 | 116 | } |
116 | | - if ( !$ok ) { |
117 | | - // This is very weird. Maybe the article was deleted or the user was blocked/desysopped in the meantime? |
118 | | - // Just throw an unknown error in this case, as it's very likely to be a race condition |
119 | | - $this->dieUsageMsg( array() ); |
120 | | - } |
121 | 117 | $res = array( |
122 | 118 | 'title' => $titleObj->getPrefixedText(), |
123 | 119 | 'reason' => $params['reason'] |
Index: trunk/phase3/includes/Title.php |
— | — | @@ -2219,66 +2219,24 @@ |
2220 | 2220 | /** |
2221 | 2221 | * Update the title protection status |
2222 | 2222 | * |
| 2223 | + * @deprecated in 1.19; will be removed in 1.20. Use WikiPage::doUpdateRestrictions() instead. |
2223 | 2224 | * @param $create_perm String Permission required for creation |
2224 | 2225 | * @param $reason String Reason for protection |
2225 | 2226 | * @param $expiry String Expiry timestamp |
2226 | 2227 | * @return boolean true |
2227 | 2228 | */ |
2228 | 2229 | public function updateTitleProtection( $create_perm, $reason, $expiry ) { |
2229 | | - global $wgUser, $wgContLang; |
| 2230 | + wfDeprecated( __METHOD__, '1.19' ); |
2230 | 2231 | |
2231 | | - if ( $create_perm == implode( ',', $this->getRestrictions( 'create' ) ) |
2232 | | - && $expiry == $this->mRestrictionsExpiry['create'] ) { |
2233 | | - // No change |
2234 | | - return true; |
2235 | | - } |
| 2232 | + global $wgUser; |
2236 | 2233 | |
2237 | | - list ( $namespace, $title ) = array( $this->getNamespace(), $this->getDBkey() ); |
| 2234 | + $imit = array( 'create' => $create_perm ); |
| 2235 | + $expiry = array( 'create' => $expiry ); |
2238 | 2236 | |
2239 | | - $dbw = wfGetDB( DB_MASTER ); |
| 2237 | + $page = WikiPage::factory( $this ); |
| 2238 | + $status = $page->doUpdateRestrictions( $limit, $expiry, false, $reason, $wgUser ); |
2240 | 2239 | |
2241 | | - $encodedExpiry = $dbw->encodeExpiry( $expiry ); |
2242 | | - |
2243 | | - $expiry_description = ''; |
2244 | | - if ( $encodedExpiry != $dbw->getInfinity() ) { |
2245 | | - $expiry_description = ' (' . wfMsgForContent( 'protect-expiring', $wgContLang->timeanddate( $expiry ), |
2246 | | - $wgContLang->date( $expiry ) , $wgContLang->time( $expiry ) ) . ')'; |
2247 | | - } else { |
2248 | | - $expiry_description .= ' (' . wfMsgForContent( 'protect-expiry-indefinite' ) . ')'; |
2249 | | - } |
2250 | | - |
2251 | | - # Update protection table |
2252 | | - if ( $create_perm != '' ) { |
2253 | | - $this->mTitleProtection = array( |
2254 | | - 'pt_namespace' => $namespace, |
2255 | | - 'pt_title' => $title, |
2256 | | - 'pt_create_perm' => $create_perm, |
2257 | | - 'pt_timestamp' => $dbw->encodeExpiry( wfTimestampNow() ), |
2258 | | - 'pt_expiry' => $encodedExpiry, |
2259 | | - 'pt_user' => $wgUser->getId(), |
2260 | | - 'pt_reason' => $reason, |
2261 | | - ); |
2262 | | - $dbw->replace( 'protected_titles', array( array( 'pt_namespace', 'pt_title' ) ), |
2263 | | - $this->mTitleProtection, __METHOD__ ); |
2264 | | - } else { |
2265 | | - $dbw->delete( 'protected_titles', array( 'pt_namespace' => $namespace, |
2266 | | - 'pt_title' => $title ), __METHOD__ ); |
2267 | | - $this->mTitleProtection = false; |
2268 | | - } |
2269 | | - |
2270 | | - # Update the protection log |
2271 | | - if ( $dbw->affectedRows() ) { |
2272 | | - $log = new LogPage( 'protect' ); |
2273 | | - |
2274 | | - if ( $create_perm ) { |
2275 | | - $params = array( "[create=$create_perm] $expiry_description", '' ); |
2276 | | - $log->addEntry( ( isset( $this->mRestrictions['create'] ) && $this->mRestrictions['create'] ) ? 'modify' : 'protect', $this, trim( $reason ), $params ); |
2277 | | - } else { |
2278 | | - $log->addEntry( 'unprotect', $this, $reason ); |
2279 | | - } |
2280 | | - } |
2281 | | - |
2282 | | - return true; |
| 2240 | + return $status->isOK(); |
2283 | 2241 | } |
2284 | 2242 | |
2285 | 2243 | /** |
— | — | @@ -2665,6 +2623,15 @@ |
2666 | 2624 | } |
2667 | 2625 | |
2668 | 2626 | /** |
| 2627 | + * Flush the protection cache in this object and force reload from the database. |
| 2628 | + * This is used when updating protection from WikiPage::doUpdateRestrictions(). |
| 2629 | + */ |
| 2630 | + public function flushRestrictions() { |
| 2631 | + $this->mRestrictionsLoaded = false; |
| 2632 | + $this->mTitleProtection = null; |
| 2633 | + } |
| 2634 | + |
| 2635 | + /** |
2669 | 2636 | * Purge expired restrictions from the page_restrictions table |
2670 | 2637 | */ |
2671 | 2638 | static function purgeExpiredRestrictions() { |
Index: trunk/phase3/includes/WikiPage.php |
— | — | @@ -1324,9 +1324,8 @@ |
1325 | 1325 | |
1326 | 1326 | /** |
1327 | 1327 | * Update the article's restriction field, and leave a log entry. |
| 1328 | + * This works for protection both existing and non-existing pages. |
1328 | 1329 | * |
1329 | | - * @todo: seperate the business/permission stuff out from backend code |
1330 | | - * |
1331 | 1330 | * @param $limit Array: set of restriction keys |
1332 | 1331 | * @param $reason String |
1333 | 1332 | * @param &$cascade Integer. Set to false if cascading protection isn't allowed. |
— | — | @@ -1334,31 +1333,17 @@ |
1335 | 1334 | * @param $user User The user updating the restrictions |
1336 | 1335 | * @return bool true on success |
1337 | 1336 | */ |
1338 | | - public function updateRestrictions( |
1339 | | - $limit = array(), $reason = '', &$cascade = 0, $expiry = array(), User $user = null |
1340 | | - ) { |
1341 | | - global $wgUser, $wgContLang; |
1342 | | - $user = is_null( $user ) ? $wgUser : $user; |
| 1337 | + public function doUpdateRestrictions( array $limit, array $expiry, &$cascade, $reason, User $user ) { |
| 1338 | + global $wgContLang; |
1343 | 1339 | |
| 1340 | + if ( wfReadOnly() ) { |
| 1341 | + return Status::newFatal( 'readonlytext', wfReadOnlyReason() ); |
| 1342 | + } |
| 1343 | + |
1344 | 1344 | $restrictionTypes = $this->mTitle->getRestrictionTypes(); |
1345 | 1345 | |
1346 | 1346 | $id = $this->mTitle->getArticleID(); |
1347 | 1347 | |
1348 | | - if ( $id <= 0 ) { |
1349 | | - wfDebug( "updateRestrictions failed: article id $id <= 0\n" ); |
1350 | | - return false; |
1351 | | - } |
1352 | | - |
1353 | | - if ( wfReadOnly() ) { |
1354 | | - wfDebug( "updateRestrictions failed: read-only\n" ); |
1355 | | - return false; |
1356 | | - } |
1357 | | - |
1358 | | - if ( count( $this->mTitle->getUserPermissionsErrors( 'protect', $user ) ) ) { |
1359 | | - wfDebug( "updateRestrictions failed: insufficient permissions\n" ); |
1360 | | - return false; |
1361 | | - } |
1362 | | - |
1363 | 1348 | if ( !$cascade ) { |
1364 | 1349 | $cascade = false; |
1365 | 1350 | } |
— | — | @@ -1368,151 +1353,182 @@ |
1369 | 1354 | |
1370 | 1355 | # @todo FIXME: Same limitations as described in ProtectionForm.php (line 37); |
1371 | 1356 | # we expect a single selection, but the schema allows otherwise. |
1372 | | - $current = array(); |
1373 | | - $updated = self::flattenRestrictions( $limit ); |
| 1357 | + $isProtected = false; |
| 1358 | + $protect = false; |
1374 | 1359 | $changed = false; |
1375 | 1360 | |
| 1361 | + $dbw = wfGetDB( DB_MASTER ); |
| 1362 | + |
1376 | 1363 | foreach ( $restrictionTypes as $action ) { |
1377 | | - if ( isset( $expiry[$action] ) ) { |
1378 | | - # Get current restrictions on $action |
1379 | | - $aLimits = $this->mTitle->getRestrictions( $action ); |
1380 | | - $current[$action] = implode( '', $aLimits ); |
1381 | | - # Are any actual restrictions being dealt with here? |
1382 | | - $aRChanged = count( $aLimits ) || !empty( $limit[$action] ); |
| 1364 | + if ( !isset( $expiry[$action] ) ) { |
| 1365 | + $expiry[$action] = $dbw->getInfinity(); |
| 1366 | + } |
| 1367 | + if ( !isset( $limit[$action] ) ) { |
| 1368 | + $limit[$action] = ''; |
| 1369 | + } elseif ( $limit[$action] != '' ) { |
| 1370 | + $protect = true; |
| 1371 | + } |
1383 | 1372 | |
1384 | | - # If something changed, we need to log it. Checking $aRChanged |
1385 | | - # assures that "unprotecting" a page that is not protected does |
1386 | | - # not log just because the expiry was "changed". |
1387 | | - if ( $aRChanged && |
1388 | | - $this->mTitle->getRestrictionExpiry( $action ) != $expiry[$action] ) |
1389 | | - { |
| 1373 | + # Get current restrictions on $action |
| 1374 | + $current = implode( '', $this->mTitle->getRestrictions( $action ) ); |
| 1375 | + if ( $current != '' ) { |
| 1376 | + $isProtected = true; |
| 1377 | + } |
| 1378 | + |
| 1379 | + if ( $limit[$action] != $current ) { |
| 1380 | + $changed = true; |
| 1381 | + } elseif ( $limit[$action] != '' ) { |
| 1382 | + # Only check expiry change if the action is actually being |
| 1383 | + # protected, since expiry does nothing on an not-protected |
| 1384 | + # action. |
| 1385 | + if ( $this->mTitle->getRestrictionExpiry( $action ) != $expiry[$action] ) { |
1390 | 1386 | $changed = true; |
1391 | 1387 | } |
1392 | 1388 | } |
1393 | 1389 | } |
1394 | 1390 | |
1395 | | - $current = self::flattenRestrictions( $current ); |
| 1391 | + if ( !$changed && $protect && $this->mTitle->areRestrictionsCascading() != $cascade ) { |
| 1392 | + $changed = true; |
| 1393 | + } |
1396 | 1394 | |
1397 | | - $changed = ( $changed || $current != $updated ); |
1398 | | - $changed = $changed || ( $updated && $this->mTitle->areRestrictionsCascading() != $cascade ); |
1399 | | - $protect = ( $updated != '' ); |
1400 | | - |
1401 | 1395 | # If nothing's changed, do nothing |
1402 | | - if ( $changed ) { |
1403 | | - if ( wfRunHooks( 'ArticleProtect', array( &$this, &$user, $limit, $reason ) ) ) { |
1404 | | - $dbw = wfGetDB( DB_MASTER ); |
| 1396 | + if ( !$changed ) { |
| 1397 | + return Status::newGood(); |
| 1398 | + } |
1405 | 1399 | |
1406 | | - # Prepare a null revision to be added to the history |
1407 | | - $modified = $current != '' && $protect; |
| 1400 | + if ( !$protect ) { # No protection at all means unprotection |
| 1401 | + $revCommentMsg = 'unprotectedarticle'; |
| 1402 | + $logAction = 'unprotect'; |
| 1403 | + } elseif ( $isProtected ) { |
| 1404 | + $revCommentMsg = 'modifiedarticleprotection'; |
| 1405 | + $logAction = 'modify'; |
| 1406 | + } else { |
| 1407 | + $revCommentMsg = 'protectedarticle'; |
| 1408 | + $logAction = 'protect'; |
| 1409 | + } |
1408 | 1410 | |
1409 | | - if ( $protect ) { |
1410 | | - $comment_type = $modified ? 'modifiedarticleprotection' : 'protectedarticle'; |
| 1411 | + $encodedExpiry = array(); |
| 1412 | + $protectDescription = ''; |
| 1413 | + foreach ( $limit as $action => $restrictions ) { |
| 1414 | + $encodedExpiry[$action] = $dbw->encodeExpiry( $expiry[$action] ); |
| 1415 | + if ( $restrictions != '' ) { |
| 1416 | + $protectDescription .= $wgContLang->getDirMark() . "[$action=$restrictions] ("; |
| 1417 | + if ( $encodedExpiry[$action] != 'infinity' ) { |
| 1418 | + $protectDescription .= wfMsgForContent( 'protect-expiring', |
| 1419 | + $wgContLang->timeanddate( $expiry[$action], false, false ) , |
| 1420 | + $wgContLang->date( $expiry[$action], false, false ) , |
| 1421 | + $wgContLang->time( $expiry[$action], false, false ) ); |
1411 | 1422 | } else { |
1412 | | - $comment_type = 'unprotectedarticle'; |
| 1423 | + $protectDescription .= wfMsgForContent( 'protect-expiry-indefinite' ); |
1413 | 1424 | } |
1414 | 1425 | |
1415 | | - $comment = $wgContLang->ucfirst( wfMsgForContent( $comment_type, $this->mTitle->getPrefixedText() ) ); |
| 1426 | + $protectDescription .= ') '; |
| 1427 | + } |
| 1428 | + } |
| 1429 | + $protectDescription = trim( $protectDescription ); |
1416 | 1430 | |
1417 | | - # Only restrictions with the 'protect' right can cascade... |
1418 | | - # Otherwise, people who cannot normally protect can "protect" pages via transclusion |
1419 | | - $editrestriction = isset( $limit['edit'] ) ? array( $limit['edit'] ) : $this->mTitle->getRestrictions( 'edit' ); |
| 1431 | + if ( $id ) { # Protection of existing page |
| 1432 | + if ( !wfRunHooks( 'ArticleProtect', array( &$this, &$user, $limit, $reason ) ) ) { |
| 1433 | + return Status::newGood(); |
| 1434 | + } |
1420 | 1435 | |
1421 | | - # The schema allows multiple restrictions |
1422 | | - if ( !in_array( 'protect', $editrestriction ) && !in_array( 'sysop', $editrestriction ) ) { |
1423 | | - $cascade = false; |
1424 | | - } |
| 1436 | + # Only restrictions with the 'protect' right can cascade... |
| 1437 | + # Otherwise, people who cannot normally protect can "protect" pages via transclusion |
| 1438 | + $editrestriction = isset( $limit['edit'] ) ? array( $limit['edit'] ) : $this->mTitle->getRestrictions( 'edit' ); |
1425 | 1439 | |
1426 | | - $cascade_description = ''; |
| 1440 | + # The schema allows multiple restrictions |
| 1441 | + if ( !in_array( 'protect', $editrestriction ) && !in_array( 'sysop', $editrestriction ) ) { |
| 1442 | + $cascade = false; |
| 1443 | + } |
1427 | 1444 | |
1428 | | - if ( $cascade ) { |
1429 | | - $cascade_description = ' [' . wfMsgForContent( 'protect-summary-cascade' ) . ']'; |
| 1445 | + # Update restrictions table |
| 1446 | + foreach ( $limit as $action => $restrictions ) { |
| 1447 | + if ( $restrictions != '' ) { |
| 1448 | + $dbw->replace( 'page_restrictions', array( array( 'pr_page', 'pr_type' ) ), |
| 1449 | + array( 'pr_page' => $id, |
| 1450 | + 'pr_type' => $action, |
| 1451 | + 'pr_level' => $restrictions, |
| 1452 | + 'pr_cascade' => ( $cascade && $action == 'edit' ) ? 1 : 0, |
| 1453 | + 'pr_expiry' => $encodedExpiry[$action] |
| 1454 | + ), |
| 1455 | + __METHOD__ |
| 1456 | + ); |
| 1457 | + } else { |
| 1458 | + $dbw->delete( 'page_restrictions', array( 'pr_page' => $id, |
| 1459 | + 'pr_type' => $action ), __METHOD__ ); |
1430 | 1460 | } |
| 1461 | + } |
1431 | 1462 | |
1432 | | - if ( $reason ) { |
1433 | | - $comment .= ": $reason"; |
1434 | | - } |
| 1463 | + # Prepare a null revision to be added to the history |
| 1464 | + $editComment = $wgContLang->ucfirst( wfMsgForContent( $revCommentMsg, $this->mTitle->getPrefixedText() ) ); |
| 1465 | + if ( $reason ) { |
| 1466 | + $editComment .= ": $reason"; |
| 1467 | + } |
| 1468 | + if ( $protectDescription ) { |
| 1469 | + $editComment .= " ($protectDescription)"; |
| 1470 | + } |
| 1471 | + if ( $cascade ) { |
| 1472 | + $editComment .= ' [' . wfMsgForContent( 'protect-summary-cascade' ) . ']'; |
| 1473 | + } |
1435 | 1474 | |
1436 | | - $editComment = $comment; |
1437 | | - $encodedExpiry = array(); |
1438 | | - $protect_description = ''; |
1439 | | - foreach ( $limit as $action => $restrictions ) { |
1440 | | - if ( !isset( $expiry[$action] ) ) |
1441 | | - $expiry[$action] = $dbw->getInfinity(); |
| 1475 | + # Insert a null revision |
| 1476 | + $nullRevision = Revision::newNullRevision( $dbw, $id, $editComment, true ); |
| 1477 | + $nullRevId = $nullRevision->insertOn( $dbw ); |
1442 | 1478 | |
1443 | | - $encodedExpiry[$action] = $dbw->encodeExpiry( $expiry[$action] ); |
1444 | | - if ( $restrictions != '' ) { |
1445 | | - $protect_description .= $wgContLang->getDirMark() . "[$action=$restrictions] ("; |
1446 | | - if ( $encodedExpiry[$action] != 'infinity' ) { |
1447 | | - $protect_description .= wfMsgForContent( 'protect-expiring', |
1448 | | - $wgContLang->timeanddate( $expiry[$action], false, false ) , |
1449 | | - $wgContLang->date( $expiry[$action], false, false ) , |
1450 | | - $wgContLang->time( $expiry[$action], false, false ) ); |
1451 | | - } else { |
1452 | | - $protect_description .= wfMsgForContent( 'protect-expiry-indefinite' ); |
1453 | | - } |
| 1479 | + $latest = $this->getLatest(); |
| 1480 | + # Update page record |
| 1481 | + $dbw->update( 'page', |
| 1482 | + array( /* SET */ |
| 1483 | + 'page_touched' => $dbw->timestamp(), |
| 1484 | + 'page_restrictions' => '', |
| 1485 | + 'page_latest' => $nullRevId |
| 1486 | + ), array( /* WHERE */ |
| 1487 | + 'page_id' => $id |
| 1488 | + ), __METHOD__ |
| 1489 | + ); |
1454 | 1490 | |
1455 | | - $protect_description .= ') '; |
1456 | | - } |
1457 | | - } |
1458 | | - $protect_description = trim( $protect_description ); |
| 1491 | + wfRunHooks( 'NewRevisionFromEditComplete', array( $this, $nullRevision, $latest, $user ) ); |
| 1492 | + wfRunHooks( 'ArticleProtectComplete', array( &$this, &$user, $limit, $reason ) ); |
| 1493 | + } else { # Protection of non-existing page (also known as "title protection") |
| 1494 | + # Cascade protection is meaningless in this case |
| 1495 | + $cascade = false; |
1459 | 1496 | |
1460 | | - if ( $protect_description && $protect ) { |
1461 | | - $editComment .= " ($protect_description)"; |
1462 | | - } |
1463 | | - |
1464 | | - if ( $cascade ) { |
1465 | | - $editComment .= "$cascade_description"; |
1466 | | - } |
1467 | | - |
1468 | | - # Update restrictions table |
1469 | | - foreach ( $limit as $action => $restrictions ) { |
1470 | | - if ( $restrictions != '' ) { |
1471 | | - $dbw->replace( 'page_restrictions', array( array( 'pr_page', 'pr_type' ) ), |
1472 | | - array( 'pr_page' => $id, |
1473 | | - 'pr_type' => $action, |
1474 | | - 'pr_level' => $restrictions, |
1475 | | - 'pr_cascade' => ( $cascade && $action == 'edit' ) ? 1 : 0, |
1476 | | - 'pr_expiry' => $encodedExpiry[$action] |
1477 | | - ), |
1478 | | - __METHOD__ |
1479 | | - ); |
1480 | | - } else { |
1481 | | - $dbw->delete( 'page_restrictions', array( 'pr_page' => $id, |
1482 | | - 'pr_type' => $action ), __METHOD__ ); |
1483 | | - } |
1484 | | - } |
1485 | | - |
1486 | | - # Insert a null revision |
1487 | | - $nullRevision = Revision::newNullRevision( $dbw, $id, $editComment, true ); |
1488 | | - $nullRevId = $nullRevision->insertOn( $dbw ); |
1489 | | - |
1490 | | - $latest = $this->getLatest(); |
1491 | | - # Update page record |
1492 | | - $dbw->update( 'page', |
1493 | | - array( /* SET */ |
1494 | | - 'page_touched' => $dbw->timestamp(), |
1495 | | - 'page_restrictions' => '', |
1496 | | - 'page_latest' => $nullRevId |
1497 | | - ), array( /* WHERE */ |
1498 | | - 'page_id' => $id |
| 1497 | + if ( $limit['create'] != '' ) { |
| 1498 | + $dbw->replace( 'protected_titles', |
| 1499 | + array( array( 'pt_namespace', 'pt_title' ) ), |
| 1500 | + array( |
| 1501 | + 'pt_namespace' => $this->mTitle->getNamespace(), |
| 1502 | + 'pt_title' => $this->mTitle->getDBkey(), |
| 1503 | + 'pt_create_perm' => $limit['create'], |
| 1504 | + 'pt_timestamp' => $dbw->encodeExpiry( wfTimestampNow() ), |
| 1505 | + 'pt_expiry' => $encodedExpiry['create'], |
| 1506 | + 'pt_user' => $user->getId(), |
| 1507 | + 'pt_reason' => $reason, |
1499 | 1508 | ), __METHOD__ |
1500 | 1509 | ); |
| 1510 | + } else { |
| 1511 | + $dbw->delete( 'protected_titles', |
| 1512 | + array( |
| 1513 | + 'pt_namespace' => $this->mTitle->getNamespace(), |
| 1514 | + 'pt_title' => $this->mTitle->getDBkey() |
| 1515 | + ), __METHOD__ |
| 1516 | + ); |
| 1517 | + } |
| 1518 | + } |
1501 | 1519 | |
1502 | | - wfRunHooks( 'NewRevisionFromEditComplete', array( $this, $nullRevision, $latest, $user ) ); |
1503 | | - wfRunHooks( 'ArticleProtectComplete', array( &$this, &$user, $limit, $reason ) ); |
| 1520 | + $this->mTitle->flushRestrictions(); |
1504 | 1521 | |
1505 | | - # Update the protection log |
1506 | | - $log = new LogPage( 'protect' ); |
1507 | | - if ( $protect ) { |
1508 | | - $params = array( $protect_description, $cascade ? 'cascade' : '' ); |
1509 | | - $log->addEntry( $modified ? 'modify' : 'protect', $this->mTitle, trim( $reason ), $params ); |
1510 | | - } else { |
1511 | | - $log->addEntry( 'unprotect', $this->mTitle, $reason ); |
1512 | | - } |
1513 | | - } # End hook |
1514 | | - } # End "changed" check |
| 1522 | + if ( $logAction == 'unprotect' ) { |
| 1523 | + $logParams = array(); |
| 1524 | + } else { |
| 1525 | + $logParams = array( $protectDescription, $cascade ? 'cascade' : '' ); |
| 1526 | + } |
1515 | 1527 | |
1516 | | - return true; |
| 1528 | + # Update the protection log |
| 1529 | + $log = new LogPage( 'protect' ); |
| 1530 | + $log->addEntry( $logAction, $this->mTitle, trim( $reason ), $logParams ); |
| 1531 | + |
| 1532 | + return Status::newGood(); |
1517 | 1533 | } |
1518 | 1534 | |
1519 | 1535 | /** |
— | — | @@ -2684,6 +2700,27 @@ |
2685 | 2701 | } |
2686 | 2702 | |
2687 | 2703 | /** |
| 2704 | + * Update the article's restriction field, and leave a log entry. |
| 2705 | + * |
| 2706 | + * @deprecated since 1.19 |
| 2707 | + * @param $limit Array: set of restriction keys |
| 2708 | + * @param $reason String |
| 2709 | + * @param &$cascade Integer. Set to false if cascading protection isn't allowed. |
| 2710 | + * @param $expiry Array: per restriction type expiration |
| 2711 | + * @param $user User The user updating the restrictions |
| 2712 | + * @return bool true on success |
| 2713 | + */ |
| 2714 | + public function updateRestrictions( |
| 2715 | + $limit = array(), $reason = '', &$cascade = 0, $expiry = array(), User $user = null |
| 2716 | + ) { |
| 2717 | + global $wgUser; |
| 2718 | + |
| 2719 | + $user = is_null( $user ) ? $wgUser : $user; |
| 2720 | + |
| 2721 | + return $this->doUpdateRestrictions( $limit, $expiry, $cascade, $reason, $user )->isOK(); |
| 2722 | + } |
| 2723 | + |
| 2724 | + /** |
2688 | 2725 | * @deprecated since 1.18 |
2689 | 2726 | */ |
2690 | 2727 | public function quickEdit( $text, $comment = '', $minor = 0 ) { |