function execute( $par ) {
		$this->setHeaders();
		$this->outputHeader();

		// Purge expired entries on one in every 10 queries
		if ( !mt_rand( 0, 10 ) ) {
			Title::purgeExpiredRestrictions();
		}

		$request = $this->getRequest();
		$type = $request->getVal( $this->IdType );
		$level = $request->getVal( $this->IdLevel );
		$sizetype = $request->getVal( 'sizetype' );
		$size = $request->getIntOrNull( 'size' );
		$NS = $request->getIntOrNull( 'namespace' );

		$pager = new ProtectedTitlesPager( $this, array(), $type, $level, $NS, $sizetype, $size );

		$this->getOutput()->addHTML( $this->showOptions( $NS, $type, $level ) );

		if ( $pager->getNumRows() ) {
			$this->getOutput()->addHTML(
				$pager->getNavigationBar() .
					'<ul>' . $pager->getBody() . '</ul>' .
					$pager->getNavigationBar()
			);
		} else {
			$this->getOutput()->addWikiMsg( 'protectedtitlesempty' );
		}
	}
 function execute($par)
 {
     global $wgOut, $wgRequest;
     $this->setHeaders();
     $this->outputHeader();
     // Purge expired entries on one in every 10 queries
     if (!mt_rand(0, 10)) {
         Title::purgeExpiredRestrictions();
     }
     $type = $wgRequest->getVal($this->IdType);
     $level = $wgRequest->getVal($this->IdLevel);
     $sizetype = $wgRequest->getVal('sizetype');
     $size = $wgRequest->getIntOrNull('size');
     $NS = $wgRequest->getIntOrNull('namespace');
     $pager = new ProtectedTitlesPager($this, array(), $type, $level, $NS, $sizetype, $size);
     $wgOut->addHTML($this->showOptions($NS, $type, $level));
     if ($pager->getNumRows()) {
         $s = $pager->getNavigationBar();
         $s .= "<ul>" . $pager->getBody() . "</ul>";
         $s .= $pager->getNavigationBar();
     } else {
         $s = '<p>' . wfMsgHtml('protectedtitlesempty') . '</p>';
     }
     $wgOut->addHTML($s);
 }
 public function execute($par)
 {
     $this->setHeaders();
     $this->outputHeader();
     $this->getOutput()->addModuleStyles('mediawiki.special');
     // Purge expired entries on one in every 10 queries
     if (!mt_rand(0, 10)) {
         Title::purgeExpiredRestrictions();
     }
     $request = $this->getRequest();
     $type = $request->getVal($this->IdType);
     $level = $request->getVal($this->IdLevel);
     $sizetype = $request->getVal('sizetype');
     $size = $request->getIntOrNull('size');
     $ns = $request->getIntOrNull('namespace');
     $indefOnly = $request->getBool('indefonly') ? 1 : 0;
     $cascadeOnly = $request->getBool('cascadeonly') ? 1 : 0;
     $noRedirect = $request->getBool('noredirect') ? 1 : 0;
     $pager = new ProtectedPagesPager($this, array(), $type, $level, $ns, $sizetype, $size, $indefOnly, $cascadeOnly, $noRedirect);
     $this->getOutput()->addHTML($this->showOptions($ns, $type, $level, $sizetype, $size, $indefOnly, $cascadeOnly, $noRedirect));
     if ($pager->getNumRows()) {
         $this->getOutput()->addHTML($pager->getNavigationBar() . $pager->getBody() . $pager->getNavigationBar());
     } else {
         $this->getOutput()->addWikiMsg('protectedpagesempty');
     }
 }
Example #4
0
 public function showList($msg = '')
 {
     global $wgOut, $wgRequest;
     if ("" != $msg) {
         $wgOut->setSubtitle($msg);
     }
     // Purge expired entries on one in every 10 queries
     if (!mt_rand(0, 10)) {
         Title::purgeExpiredRestrictions();
     }
     $type = $wgRequest->getVal($this->IdType);
     $level = $wgRequest->getVal($this->IdLevel);
     $sizetype = $wgRequest->getVal('sizetype');
     $size = $wgRequest->getIntOrNull('size');
     $NS = $wgRequest->getIntOrNull('namespace');
     $indefOnly = $wgRequest->getBool('indefonly') ? 1 : 0;
     $cascadeOnly = $wgRequest->getBool('cascadeonly') ? 1 : 0;
     $pager = new ProtectedPagesPager($this, array(), $type, $level, $NS, $sizetype, $size, $indefOnly, $cascadeOnly);
     $wgOut->addHTML($this->showOptions($NS, $type, $level, $sizetype, $size, $indefOnly, $cascadeOnly));
     if ($pager->getNumRows()) {
         $s = $pager->getNavigationBar();
         $s .= "<ul>" . $pager->getBody() . "</ul>";
         $s .= $pager->getNavigationBar();
     } else {
         $s = '<p>' . wfMsgHtml('protectedpagesempty') . '</p>';
     }
     $wgOut->addHTML($s);
 }
Example #5
0
	/**
	 * Update the article's restriction field, and leave a log entry.
	 * This works for protection both existing and non-existing pages.
	 *
	 * @param array $limit set of restriction keys
	 * @param array $expiry per restriction type expiration
	 * @param int &$cascade Set to false if cascading protection isn't allowed.
	 * @param string $reason
	 * @param User $user The user updating the restrictions
	 * @return Status
	 */
	public function doUpdateRestrictions( array $limit, array $expiry, &$cascade, $reason, User $user ) {
		global $wgCascadingRestrictionLevels;

		if ( wfReadOnly() ) {
			return Status::newFatal( 'readonlytext', wfReadOnlyReason() );
		}

		$restrictionTypes = $this->mTitle->getRestrictionTypes();

		$id = $this->getId();

		if ( !$cascade ) {
			$cascade = false;
		}

		// Take this opportunity to purge out expired restrictions
		Title::purgeExpiredRestrictions();

		// @todo FIXME: Same limitations as described in ProtectionForm.php (line 37);
		// we expect a single selection, but the schema allows otherwise.
		$isProtected = false;
		$protect = false;
		$changed = false;

		$dbw = wfGetDB( DB_MASTER );

		foreach ( $restrictionTypes as $action ) {
			if ( !isset( $expiry[$action] ) ) {
				$expiry[$action] = $dbw->getInfinity();
			}
			if ( !isset( $limit[$action] ) ) {
				$limit[$action] = '';
			} elseif ( $limit[$action] != '' ) {
				$protect = true;
			}

			// Get current restrictions on $action
			$current = implode( '', $this->mTitle->getRestrictions( $action ) );
			if ( $current != '' ) {
				$isProtected = true;
			}

			if ( $limit[$action] != $current ) {
				$changed = true;
			} elseif ( $limit[$action] != '' ) {
				// Only check expiry change if the action is actually being
				// protected, since expiry does nothing on an not-protected
				// action.
				if ( $this->mTitle->getRestrictionExpiry( $action ) != $expiry[$action] ) {
					$changed = true;
				}
			}
		}

		if ( !$changed && $protect && $this->mTitle->areRestrictionsCascading() != $cascade ) {
			$changed = true;
		}

		// If nothing has changed, do nothing
		if ( !$changed ) {
			return Status::newGood();
		}

		if ( !$protect ) { // No protection at all means unprotection
			$revCommentMsg = 'unprotectedarticle';
			$logAction = 'unprotect';
		} elseif ( $isProtected ) {
			$revCommentMsg = 'modifiedarticleprotection';
			$logAction = 'modify';
		} else {
			$revCommentMsg = 'protectedarticle';
			$logAction = 'protect';
		}

		if ( $id ) { // Protection of existing page
			if ( !wfRunHooks( 'ArticleProtect', array( &$this, &$user, $limit, $reason ) ) ) {
				return Status::newGood();
			}

			// Only certain restrictions can cascade...
			$editrestriction = isset( $limit['edit'] ) ? array( $limit['edit'] ) : $this->mTitle->getRestrictions( 'edit' );
			foreach ( array_keys( $editrestriction, 'sysop' ) as $key ) {
				$editrestriction[$key] = 'editprotected'; // backwards compatibility
			}
			foreach ( array_keys( $editrestriction, 'autoconfirmed' ) as $key ) {
				$editrestriction[$key] = 'editsemiprotected'; // backwards compatibility
			}

			$cascadingRestrictionLevels = $wgCascadingRestrictionLevels;
			foreach ( array_keys( $cascadingRestrictionLevels, 'sysop' ) as $key ) {
				$cascadingRestrictionLevels[$key] = 'editprotected'; // backwards compatibility
			}
			foreach ( array_keys( $cascadingRestrictionLevels, 'autoconfirmed' ) as $key ) {
				$cascadingRestrictionLevels[$key] = 'editsemiprotected'; // backwards compatibility
			}

			// The schema allows multiple restrictions
			if ( !array_intersect( $editrestriction, $cascadingRestrictionLevels ) ) {
				$cascade = false;
			}

			// insert null revision to identify the page protection change as edit summary
			$latest = $this->getLatest();
			$nullRevision = $this->insertProtectNullRevision( $revCommentMsg, $limit, $expiry, $cascade, $reason );
			if ( $nullRevision === null ) {
				return Status::newFatal( 'no-null-revision', $this->mTitle->getPrefixedText() );
			}

			// Update restrictions table
			foreach ( $limit as $action => $restrictions ) {
				if ( $restrictions != '' ) {
					$dbw->replace( 'page_restrictions', array( array( 'pr_page', 'pr_type' ) ),
						array( 'pr_page' => $id,
							'pr_type' => $action,
							'pr_level' => $restrictions,
							'pr_cascade' => ( $cascade && $action == 'edit' ) ? 1 : 0,
							'pr_expiry' => $dbw->encodeExpiry( $expiry[$action] )
						),
						__METHOD__
					);
				} else {
					$dbw->delete( 'page_restrictions', array( 'pr_page' => $id,
						'pr_type' => $action ), __METHOD__ );
				}
			}

			// Clear out legacy restriction fields
			$dbw->update(
				'page',
				array( 'page_restrictions' => '' ),
				array( 'page_id' => $id ),
				__METHOD__
			);

			wfRunHooks( 'NewRevisionFromEditComplete', array( $this, $nullRevision, $latest, $user ) );
			wfRunHooks( 'ArticleProtectComplete', array( &$this, &$user, $limit, $reason ) );
		} else { // Protection of non-existing page (also known as "title protection")
			// Cascade protection is meaningless in this case
			$cascade = false;

			if ( $limit['create'] != '' ) {
				$dbw->replace( 'protected_titles',
					array( array( 'pt_namespace', 'pt_title' ) ),
					array(
						'pt_namespace' => $this->mTitle->getNamespace(),
						'pt_title' => $this->mTitle->getDBkey(),
						'pt_create_perm' => $limit['create'],
						'pt_timestamp' => $dbw->encodeExpiry( wfTimestampNow() ),
						'pt_expiry' => $dbw->encodeExpiry( $expiry['create'] ),
						'pt_user' => $user->getId(),
						'pt_reason' => $reason,
					), __METHOD__
				);
			} else {
				$dbw->delete( 'protected_titles',
					array(
						'pt_namespace' => $this->mTitle->getNamespace(),
						'pt_title' => $this->mTitle->getDBkey()
					), __METHOD__
				);
			}
		}

		$this->mTitle->flushRestrictions();
		InfoAction::invalidateCache( $this->mTitle );

		if ( $logAction == 'unprotect' ) {
			$params = array();
		} else {
			$protectDescriptionLog = $this->protectDescriptionLog( $limit, $expiry );
			$params = array( $protectDescriptionLog, $cascade ? 'cascade' : '' );
		}

		// Update the protection log
		$log = new LogPage( 'protect' );
		$log->addEntry( $logAction, $this->mTitle, trim( $reason ), $params, $user );

		return Status::newGood();
	}
Example #6
0
 /**
  * Update the article's restriction field, and leave a log entry.
  * This works for protection both existing and non-existing pages.
  *
  * @param array $limit Set of restriction keys
  * @param array $expiry Per restriction type expiration
  * @param int &$cascade Set to false if cascading protection isn't allowed.
  * @param string $reason
  * @param User $user The user updating the restrictions
  * @param string|string[] $tags Change tags to add to the pages and protection log entries
  *   ($user should be able to add the specified tags before this is called)
  * @return Status Status object; if action is taken, $status->value is the log_id of the
  *   protection log entry.
  */
 public function doUpdateRestrictions(array $limit, array $expiry, &$cascade, $reason, User $user, $tags = null)
 {
     global $wgCascadingRestrictionLevels, $wgContLang;
     if (wfReadOnly()) {
         return Status::newFatal('readonlytext', wfReadOnlyReason());
     }
     $this->loadPageData('fromdbmaster');
     $restrictionTypes = $this->mTitle->getRestrictionTypes();
     $id = $this->getId();
     if (!$cascade) {
         $cascade = false;
     }
     // Take this opportunity to purge out expired restrictions
     Title::purgeExpiredRestrictions();
     // @todo FIXME: Same limitations as described in ProtectionForm.php (line 37);
     // we expect a single selection, but the schema allows otherwise.
     $isProtected = false;
     $protect = false;
     $changed = false;
     $dbw = wfGetDB(DB_MASTER);
     foreach ($restrictionTypes as $action) {
         if (!isset($expiry[$action]) || $expiry[$action] === $dbw->getInfinity()) {
             $expiry[$action] = 'infinity';
         }
         if (!isset($limit[$action])) {
             $limit[$action] = '';
         } elseif ($limit[$action] != '') {
             $protect = true;
         }
         // Get current restrictions on $action
         $current = implode('', $this->mTitle->getRestrictions($action));
         if ($current != '') {
             $isProtected = true;
         }
         if ($limit[$action] != $current) {
             $changed = true;
         } elseif ($limit[$action] != '') {
             // Only check expiry change if the action is actually being
             // protected, since expiry does nothing on an not-protected
             // action.
             if ($this->mTitle->getRestrictionExpiry($action) != $expiry[$action]) {
                 $changed = true;
             }
         }
     }
     if (!$changed && $protect && $this->mTitle->areRestrictionsCascading() != $cascade) {
         $changed = true;
     }
     // If nothing has changed, do nothing
     if (!$changed) {
         return Status::newGood();
     }
     if (!$protect) {
         // No protection at all means unprotection
         $revCommentMsg = 'unprotectedarticle';
         $logAction = 'unprotect';
     } elseif ($isProtected) {
         $revCommentMsg = 'modifiedarticleprotection';
         $logAction = 'modify';
     } else {
         $revCommentMsg = 'protectedarticle';
         $logAction = 'protect';
     }
     // Truncate for whole multibyte characters
     $reason = $wgContLang->truncate($reason, 255);
     $logRelationsValues = [];
     $logRelationsField = null;
     $logParamsDetails = [];
     // Null revision (used for change tag insertion)
     $nullRevision = null;
     if ($id) {
         // Protection of existing page
         if (!Hooks::run('ArticleProtect', [&$this, &$user, $limit, $reason])) {
             return Status::newGood();
         }
         // Only certain restrictions can cascade...
         $editrestriction = isset($limit['edit']) ? [$limit['edit']] : $this->mTitle->getRestrictions('edit');
         foreach (array_keys($editrestriction, 'sysop') as $key) {
             $editrestriction[$key] = 'editprotected';
             // backwards compatibility
         }
         foreach (array_keys($editrestriction, 'autoconfirmed') as $key) {
             $editrestriction[$key] = 'editsemiprotected';
             // backwards compatibility
         }
         $cascadingRestrictionLevels = $wgCascadingRestrictionLevels;
         foreach (array_keys($cascadingRestrictionLevels, 'sysop') as $key) {
             $cascadingRestrictionLevels[$key] = 'editprotected';
             // backwards compatibility
         }
         foreach (array_keys($cascadingRestrictionLevels, 'autoconfirmed') as $key) {
             $cascadingRestrictionLevels[$key] = 'editsemiprotected';
             // backwards compatibility
         }
         // The schema allows multiple restrictions
         if (!array_intersect($editrestriction, $cascadingRestrictionLevels)) {
             $cascade = false;
         }
         // insert null revision to identify the page protection change as edit summary
         $latest = $this->getLatest();
         $nullRevision = $this->insertProtectNullRevision($revCommentMsg, $limit, $expiry, $cascade, $reason, $user);
         if ($nullRevision === null) {
             return Status::newFatal('no-null-revision', $this->mTitle->getPrefixedText());
         }
         $logRelationsField = 'pr_id';
         // Update restrictions table
         foreach ($limit as $action => $restrictions) {
             $dbw->delete('page_restrictions', ['pr_page' => $id, 'pr_type' => $action], __METHOD__);
             if ($restrictions != '') {
                 $cascadeValue = $cascade && $action == 'edit' ? 1 : 0;
                 $dbw->insert('page_restrictions', ['pr_id' => $dbw->nextSequenceValue('page_restrictions_pr_id_seq'), 'pr_page' => $id, 'pr_type' => $action, 'pr_level' => $restrictions, 'pr_cascade' => $cascadeValue, 'pr_expiry' => $dbw->encodeExpiry($expiry[$action])], __METHOD__);
                 $logRelationsValues[] = $dbw->insertId();
                 $logParamsDetails[] = ['type' => $action, 'level' => $restrictions, 'expiry' => $expiry[$action], 'cascade' => (bool) $cascadeValue];
             }
         }
         // Clear out legacy restriction fields
         $dbw->update('page', ['page_restrictions' => ''], ['page_id' => $id], __METHOD__);
         Hooks::run('NewRevisionFromEditComplete', [$this, $nullRevision, $latest, $user]);
         Hooks::run('ArticleProtectComplete', [&$this, &$user, $limit, $reason]);
     } else {
         // Protection of non-existing page (also known as "title protection")
         // Cascade protection is meaningless in this case
         $cascade = false;
         if ($limit['create'] != '') {
             $dbw->replace('protected_titles', [['pt_namespace', 'pt_title']], ['pt_namespace' => $this->mTitle->getNamespace(), 'pt_title' => $this->mTitle->getDBkey(), 'pt_create_perm' => $limit['create'], 'pt_timestamp' => $dbw->timestamp(), 'pt_expiry' => $dbw->encodeExpiry($expiry['create']), 'pt_user' => $user->getId(), 'pt_reason' => $reason], __METHOD__);
             $logParamsDetails[] = ['type' => 'create', 'level' => $limit['create'], 'expiry' => $expiry['create']];
         } else {
             $dbw->delete('protected_titles', ['pt_namespace' => $this->mTitle->getNamespace(), 'pt_title' => $this->mTitle->getDBkey()], __METHOD__);
         }
     }
     $this->mTitle->flushRestrictions();
     InfoAction::invalidateCache($this->mTitle);
     if ($logAction == 'unprotect') {
         $params = [];
     } else {
         $protectDescriptionLog = $this->protectDescriptionLog($limit, $expiry);
         $params = ['4::description' => $protectDescriptionLog, '5:bool:cascade' => $cascade, 'details' => $logParamsDetails];
     }
     // Update the protection log
     $logEntry = new ManualLogEntry('protect', $logAction);
     $logEntry->setTarget($this->mTitle);
     $logEntry->setComment($reason);
     $logEntry->setPerformer($user);
     $logEntry->setParameters($params);
     if (!is_null($nullRevision)) {
         $logEntry->setAssociatedRevId($nullRevision->getId());
     }
     $logEntry->setTags($tags);
     if ($logRelationsField !== null && count($logRelationsValues)) {
         $logEntry->setRelations([$logRelationsField => $logRelationsValues]);
     }
     $logId = $logEntry->insert();
     $logEntry->publish($logId);
     return Status::newGood($logId);
 }
Example #7
0
 /**
  * Loads a string into mRestrictions array
  * @param resource $res restrictions as an SQL result.
  */
 private function loadRestrictionsFromRow($res, $oldFashionedRestrictions = NULL)
 {
     $dbr = wfGetDb(DB_SLAVE);
     $this->mRestrictions['edit'] = array();
     $this->mRestrictions['move'] = array();
     # Backwards-compatibility: also load the restrictions from the page record (old format).
     if ($oldFashionedRestrictions == NULL) {
         $oldFashionedRestrictions = $dbr->selectField('page', 'page_restrictions', array('page_id' => $this->getArticleId()), __METHOD__);
     }
     if ($oldFashionedRestrictions != '') {
         foreach (explode(':', trim($oldFashionedRestrictions)) as $restrict) {
             $temp = explode('=', trim($restrict));
             if (count($temp) == 1) {
                 // old old format should be treated as edit/move restriction
                 $this->mRestrictions["edit"] = explode(',', trim($temp[0]));
                 $this->mRestrictions["move"] = explode(',', trim($temp[0]));
             } else {
                 $this->mRestrictions[$temp[0]] = explode(',', trim($temp[1]));
             }
         }
         $this->mOldRestrictions = true;
         $this->mCascadeRestriction = false;
         $this->mRestrictionsExpiry = Block::decodeExpiry('');
     }
     if ($dbr->numRows($res)) {
         # Current system - load second to make them override.
         $now = wfTimestampNow();
         $purgeExpired = false;
         while ($row = $dbr->fetchObject($res)) {
             # Cycle through all the restrictions.
             // This code should be refactored, now that it's being used more generally,
             // But I don't really see any harm in leaving it in Block for now -werdna
             $expiry = Block::decodeExpiry($row->pr_expiry);
             // Only apply the restrictions if they haven't expired!
             if (!$expiry || $expiry > $now) {
                 $this->mRestrictionsExpiry = $expiry;
                 $this->mRestrictions[$row->pr_type] = explode(',', trim($row->pr_level));
                 $this->mCascadeRestriction |= $row->pr_cascade;
             } else {
                 // Trigger a lazy purge of expired restrictions
                 $purgeExpired = true;
             }
         }
         if ($purgeExpired) {
             Title::purgeExpiredRestrictions();
         }
     }
     $this->mRestrictionsLoaded = true;
 }
Example #8
0
 /**
  * Update the article's restriction field, and leave a log entry.
  *
  * @param $limit Array: set of restriction keys
  * @param $reason String
  * @param &$cascade Integer. Set to false if cascading protection isn't allowed.
  * @param $expiry Array: per restriction type expiration
  * @return bool true on success
  */
 public function updateRestrictions($limit = array(), $reason = '', &$cascade = 0, $expiry = array())
 {
     global $wgUser, $wgContLang;
     $restrictionTypes = $this->mTitle->getRestrictionTypes();
     $id = $this->mTitle->getArticleID();
     if ($id <= 0) {
         wfDebug("updateRestrictions failed: article id {$id} <= 0\n");
         return false;
     }
     if (wfReadOnly()) {
         wfDebug("updateRestrictions failed: read-only\n");
         return false;
     }
     if (!$this->mTitle->userCan('protect')) {
         wfDebug("updateRestrictions failed: insufficient permissions\n");
         return false;
     }
     if (!$cascade) {
         $cascade = false;
     }
     // Take this opportunity to purge out expired restrictions
     Title::purgeExpiredRestrictions();
     # FIXME: Same limitations as described in ProtectionForm.php (line 37);
     # we expect a single selection, but the schema allows otherwise.
     $current = array();
     $updated = Article::flattenRestrictions($limit);
     $changed = false;
     foreach ($restrictionTypes as $action) {
         if (isset($expiry[$action])) {
             # Get current restrictions on $action
             $aLimits = $this->mTitle->getRestrictions($action);
             $current[$action] = implode('', $aLimits);
             # Are any actual restrictions being dealt with here?
             $aRChanged = count($aLimits) || !empty($limit[$action]);
             # If something changed, we need to log it. Checking $aRChanged
             # assures that "unprotecting" a page that is not protected does
             # not log just because the expiry was "changed".
             if ($aRChanged && $this->mTitle->mRestrictionsExpiry[$action] != $expiry[$action]) {
                 $changed = true;
             }
         }
     }
     $current = Article::flattenRestrictions($current);
     $changed = $changed || $current != $updated;
     $changed = $changed || $updated && $this->mTitle->areRestrictionsCascading() != $cascade;
     $protect = $updated != '';
     # If nothing's changed, do nothing
     if ($changed) {
         if (wfRunHooks('ArticleProtect', array(&$this, &$wgUser, $limit, $reason))) {
             $dbw = wfGetDB(DB_MASTER);
             # Prepare a null revision to be added to the history
             $modified = $current != '' && $protect;
             if ($protect) {
                 $comment_type = $modified ? 'modifiedarticleprotection' : 'protectedarticle';
             } else {
                 $comment_type = 'unprotectedarticle';
             }
             $comment = $wgContLang->ucfirst(wfMsgForContent($comment_type, $this->mTitle->getPrefixedText()));
             # Only restrictions with the 'protect' right can cascade...
             # Otherwise, people who cannot normally protect can "protect" pages via transclusion
             $editrestriction = isset($limit['edit']) ? array($limit['edit']) : $this->mTitle->getRestrictions('edit');
             # The schema allows multiple restrictions
             if (!in_array('protect', $editrestriction) && !in_array('sysop', $editrestriction)) {
                 $cascade = false;
             }
             $cascade_description = '';
             if ($cascade) {
                 $cascade_description = ' [' . wfMsgForContent('protect-summary-cascade') . ']';
             }
             if ($reason) {
                 $comment .= ": {$reason}";
             }
             $editComment = $comment;
             $encodedExpiry = array();
             $protect_description = '';
             foreach ($limit as $action => $restrictions) {
                 if (!isset($expiry[$action])) {
                     $expiry[$action] = Block::infinity();
                 }
                 $encodedExpiry[$action] = Block::encodeExpiry($expiry[$action], $dbw);
                 if ($restrictions != '') {
                     $protect_description .= "[{$action}={$restrictions}] (";
                     if ($encodedExpiry[$action] != 'infinity') {
                         $protect_description .= wfMsgForContent('protect-expiring', $wgContLang->timeanddate($expiry[$action], false, false), $wgContLang->date($expiry[$action], false, false), $wgContLang->time($expiry[$action], false, false));
                     } else {
                         $protect_description .= wfMsgForContent('protect-expiry-indefinite');
                     }
                     $protect_description .= ') ';
                 }
             }
             $protect_description = trim($protect_description);
             if ($protect_description && $protect) {
                 $editComment .= " ({$protect_description})";
             }
             if ($cascade) {
                 $editComment .= "{$cascade_description}";
             }
             # Update restrictions table
             foreach ($limit as $action => $restrictions) {
                 if ($restrictions != '') {
                     $dbw->replace('page_restrictions', array(array('pr_page', 'pr_type')), array('pr_page' => $id, 'pr_type' => $action, 'pr_level' => $restrictions, 'pr_cascade' => $cascade && $action == 'edit' ? 1 : 0, 'pr_expiry' => $encodedExpiry[$action]), __METHOD__);
                 } else {
                     $dbw->delete('page_restrictions', array('pr_page' => $id, 'pr_type' => $action), __METHOD__);
                 }
             }
             # Insert a null revision
             $nullRevision = Revision::newNullRevision($dbw, $id, $editComment, true);
             $nullRevId = $nullRevision->insertOn($dbw);
             $latest = $this->getLatest();
             # Update page record
             $dbw->update('page', array('page_touched' => $dbw->timestamp(), 'page_restrictions' => '', 'page_latest' => $nullRevId), array('page_id' => $id), 'Article::protect');
             wfRunHooks('NewRevisionFromEditComplete', array($this, $nullRevision, $latest, $wgUser));
             wfRunHooks('ArticleProtectComplete', array(&$this, &$wgUser, $limit, $reason));
             # Update the protection log
             $log = new LogPage('protect');
             if ($protect) {
                 $params = array($protect_description, $cascade ? 'cascade' : '');
                 $log->addEntry($modified ? 'modify' : 'protect', $this->mTitle, trim($reason), $params);
             } else {
                 $log->addEntry('unprotect', $this->mTitle, $reason);
             }
         }
         # End hook
     }
     # End "changed" check
     return true;
 }
Example #9
0
 /**
  * Load restrictions from the page_restrictions table
  *
  * @param $oldFashionedRestrictions String comma-separated list of page
  *        restrictions from page table (pre 1.10)
  */
 public function loadRestrictions($oldFashionedRestrictions = null)
 {
     global $wgContLang;
     if (!$this->mRestrictionsLoaded) {
         if ($this->exists()) {
             $dbr = wfGetDB(DB_SLAVE);
             $res = $dbr->select('page_restrictions', '*', array('pr_page' => $this->getArticleId()), __METHOD__);
             $this->loadRestrictionsFromResultWrapper($res, $oldFashionedRestrictions);
         } else {
             $title_protection = $this->getTitleProtection();
             if ($title_protection) {
                 $now = wfTimestampNow();
                 $expiry = $wgContLang->formatExpiry($title_protection['pt_expiry'], TS_MW);
                 if (!$expiry || $expiry > $now) {
                     // Apply the restrictions
                     $this->mRestrictionsExpiry['create'] = $expiry;
                     $this->mRestrictions['create'] = explode(',', trim($title_protection['pt_create_perm']));
                 } else {
                     // Get rid of the old restrictions
                     Title::purgeExpiredRestrictions();
                     $this->mTitleProtection = false;
                 }
             } else {
                 $this->mRestrictionsExpiry['create'] = $wgContLang->formatExpiry('', TS_MW);
             }
             $this->mRestrictionsLoaded = true;
         }
     }
 }
Example #10
0
 /**
  * Update the article's restriction field, and leave a log entry.
  * This works for protection both existing and non-existing pages.
  *
  * @param $limit Array: set of restriction keys
  * @param $reason String
  * @param &$cascade Integer. Set to false if cascading protection isn't allowed.
  * @param $expiry Array: per restriction type expiration
  * @param $user User The user updating the restrictions
  * @return Status
  */
 public function doUpdateRestrictions(array $limit, array $expiry, &$cascade, $reason, User $user)
 {
     global $wgContLang;
     if (wfReadOnly()) {
         return Status::newFatal('readonlytext', wfReadOnlyReason());
     }
     $restrictionTypes = $this->mTitle->getRestrictionTypes();
     $id = $this->mTitle->getArticleID();
     if (!$cascade) {
         $cascade = false;
     }
     // Take this opportunity to purge out expired restrictions
     Title::purgeExpiredRestrictions();
     # @todo FIXME: Same limitations as described in ProtectionForm.php (line 37);
     # we expect a single selection, but the schema allows otherwise.
     $isProtected = false;
     $protect = false;
     $changed = false;
     $dbw = wfGetDB(DB_MASTER);
     foreach ($restrictionTypes as $action) {
         if (!isset($expiry[$action])) {
             $expiry[$action] = $dbw->getInfinity();
         }
         if (!isset($limit[$action])) {
             $limit[$action] = '';
         } elseif ($limit[$action] != '') {
             $protect = true;
         }
         # Get current restrictions on $action
         $current = implode('', $this->mTitle->getRestrictions($action));
         if ($current != '') {
             $isProtected = true;
         }
         if ($limit[$action] != $current) {
             $changed = true;
         } elseif ($limit[$action] != '') {
             # Only check expiry change if the action is actually being
             # protected, since expiry does nothing on an not-protected
             # action.
             if ($this->mTitle->getRestrictionExpiry($action) != $expiry[$action]) {
                 $changed = true;
             }
         }
     }
     if (!$changed && $protect && $this->mTitle->areRestrictionsCascading() != $cascade) {
         $changed = true;
     }
     # If nothing's changed, do nothing
     if (!$changed) {
         return Status::newGood();
     }
     if (!$protect) {
         # No protection at all means unprotection
         $revCommentMsg = 'unprotectedarticle';
         $logAction = 'unprotect';
     } elseif ($isProtected) {
         $revCommentMsg = 'modifiedarticleprotection';
         $logAction = 'modify';
     } else {
         $revCommentMsg = 'protectedarticle';
         $logAction = 'protect';
     }
     $encodedExpiry = array();
     $protectDescription = '';
     foreach ($limit as $action => $restrictions) {
         $encodedExpiry[$action] = $dbw->encodeExpiry($expiry[$action]);
         if ($restrictions != '') {
             $protectDescription .= $wgContLang->getDirMark() . "[{$action}={$restrictions}] (";
             if ($encodedExpiry[$action] != 'infinity') {
                 $protectDescription .= wfMessage('protect-expiring', $wgContLang->timeanddate($expiry[$action], false, false), $wgContLang->date($expiry[$action], false, false), $wgContLang->time($expiry[$action], false, false))->inContentLanguage()->text();
             } else {
                 $protectDescription .= wfMessage('protect-expiry-indefinite')->inContentLanguage()->text();
             }
             $protectDescription .= ') ';
         }
     }
     $protectDescription = trim($protectDescription);
     if ($id) {
         # Protection of existing page
         if (!wfRunHooks('ArticleProtect', array(&$this, &$user, $limit, $reason))) {
             return Status::newGood();
         }
         # Only restrictions with the 'protect' right can cascade...
         # Otherwise, people who cannot normally protect can "protect" pages via transclusion
         $editrestriction = isset($limit['edit']) ? array($limit['edit']) : $this->mTitle->getRestrictions('edit');
         # The schema allows multiple restrictions
         if (!in_array('protect', $editrestriction) && !in_array('sysop', $editrestriction)) {
             $cascade = false;
         }
         # Update restrictions table
         foreach ($limit as $action => $restrictions) {
             if ($restrictions != '') {
                 $dbw->replace('page_restrictions', array(array('pr_page', 'pr_type')), array('pr_page' => $id, 'pr_type' => $action, 'pr_level' => $restrictions, 'pr_cascade' => $cascade && $action == 'edit' ? 1 : 0, 'pr_expiry' => $encodedExpiry[$action]), __METHOD__);
             } else {
                 $dbw->delete('page_restrictions', array('pr_page' => $id, 'pr_type' => $action), __METHOD__);
             }
         }
         # Prepare a null revision to be added to the history
         $editComment = $wgContLang->ucfirst(wfMessage($revCommentMsg, $this->mTitle->getPrefixedText())->inContentLanguage()->text());
         if ($reason) {
             $editComment .= ": {$reason}";
         }
         if ($protectDescription) {
             $editComment .= " ({$protectDescription})";
         }
         if ($cascade) {
             // FIXME: Should use 'brackets' message.
             $editComment .= ' [' . wfMessage('protect-summary-cascade')->inContentLanguage()->text() . ']';
         }
         # Insert a null revision
         $nullRevision = Revision::newNullRevision($dbw, $id, $editComment, true);
         $nullRevId = $nullRevision->insertOn($dbw);
         $latest = $this->getLatest();
         # Update page record
         $dbw->update('page', array('page_touched' => $dbw->timestamp(), 'page_restrictions' => '', 'page_latest' => $nullRevId), array('page_id' => $id), __METHOD__);
         wfRunHooks('NewRevisionFromEditComplete', array($this, $nullRevision, $latest, $user));
         wfRunHooks('ArticleProtectComplete', array(&$this, &$user, $limit, $reason));
     } else {
         # Protection of non-existing page (also known as "title protection")
         # Cascade protection is meaningless in this case
         $cascade = false;
         if ($limit['create'] != '') {
             $dbw->replace('protected_titles', array(array('pt_namespace', 'pt_title')), array('pt_namespace' => $this->mTitle->getNamespace(), 'pt_title' => $this->mTitle->getDBkey(), 'pt_create_perm' => $limit['create'], 'pt_timestamp' => $dbw->encodeExpiry(wfTimestampNow()), 'pt_expiry' => $encodedExpiry['create'], 'pt_user' => $user->getId(), 'pt_reason' => $reason), __METHOD__);
         } else {
             $dbw->delete('protected_titles', array('pt_namespace' => $this->mTitle->getNamespace(), 'pt_title' => $this->mTitle->getDBkey()), __METHOD__);
         }
     }
     $this->mTitle->flushRestrictions();
     if ($logAction == 'unprotect') {
         $logParams = array();
     } else {
         $logParams = array($protectDescription, $cascade ? 'cascade' : '');
     }
     # Update the protection log
     $log = new LogPage('protect');
     $log->addEntry($logAction, $this->mTitle, trim($reason), $logParams, $user);
     return Status::newGood();
 }
Example #11
0
 public function loadRestrictions($oldFashionedRestrictions = NULL)
 {
     if (!$this->mRestrictionsLoaded) {
         if ($this->exists()) {
             $dbr = wfGetDB(DB_SLAVE);
             $res = $dbr->select('page_restrictions', '*', array('pr_page' => $this->getArticleId()), __METHOD__);
             $this->loadRestrictionsFromRow($res, $oldFashionedRestrictions);
         } else {
             $title_protection = $this->getTitleProtection();
             if (is_array($title_protection)) {
                 extract($title_protection);
                 $now = wfTimestampNow();
                 $expiry = Block::decodeExpiry($pt_expiry);
                 if (!$expiry || $expiry > $now) {
                     // Apply the restrictions
                     $this->mRestrictionsExpiry = $expiry;
                     $this->mRestrictions['create'] = explode(',', trim($pt_create_perm));
                 } else {
                     // Get rid of the old restrictions
                     Title::purgeExpiredRestrictions();
                 }
             }
             $this->mRestrictionsLoaded = true;
         }
     }
 }
Example #12
0
function doProtect($limit = array(), $reason = '', &$expiry = '')
{
    global $wgUser, $wgRestrictionTypes, $wgContLang, $wgTitle;
    $id = $wgTitle->getArticleID();
    if (wfReadOnly() || $id == 0) {
        return false;
    }
    if (strlen($expiry) == 0) {
        $expiry = 'infinite';
    }
    if ($expiry == 'infinite' || $expiry == 'indefinite') {
        $expiry = Block::infinity();
    } else {
        # Convert GNU-style date, on error returns -1 for PHP <5.1 and false for PHP >=5.1
        $expiry = strtotime($expiry);
        if ($expiry < 0 || $expiry === false) {
            //invalid expiry, rewrite to infinity
            $expiry = Block::infinity();
        } else {
            // Fixme: non-qualified absolute times are not in users specified timezone
            // and there isn't notice about it in the ui
            $expiry = wfTimestamp(TS_MW, $expiry);
        }
    }
    // Take this opportunity to purge out expired restrictions
    Title::purgeExpiredRestrictions();
    # FIXME: Same limitations as described in ProtectionForm.php (line 37);
    # we expect a single selection, but the schema allows otherwise.
    $current = array();
    foreach ($wgRestrictionTypes as $action) {
        $current[$action] = implode('', $wgTitle->getRestrictions($action));
    }
    $current = Article::flattenRestrictions($current);
    $updated = Article::flattenRestrictions($limit);
    $changed = $current != $updated;
    $changed = $changed || $wgTitle->mRestrictionsExpiry != $expiry;
    $protect = $updated != '';
    # If nothing's changed, do nothing
    if ($changed) {
        global $wgGroupPermissions;
        $dbw = wfGetDB(DB_MASTER);
        $encodedExpiry = Block::encodeExpiry($expiry, $dbw);
        $expiry_description = '';
        if ($encodedExpiry != 'infinity') {
            $expiry_description = ' (' . wfMsgForContent('protect-expiring', $wgContLang->timeanddate($expiry, false, false)) . ')';
        }
        # Prepare a null revision to be added to the history
        $modified = $current != '' && $protect;
        if ($protect) {
            $comment_type = $modified ? 'modifiedarticleprotection' : 'protectedarticle';
        } else {
            $comment_type = 'unprotectedarticle';
        }
        $comment = $wgContLang->ucfirst(wfMsgForContent($comment_type, $wgTitle->getPrefixedText()));
        if ($reason) {
            $comment .= ": {$reason}";
        }
        if ($protect) {
            $comment .= " [{$updated}]";
        }
        if ($expiry_description && $protect) {
            $comment .= "{$expiry_description}";
        }
        # Update restrictions table
        foreach ($limit as $action => $restrictions) {
            if ($restrictions != '') {
                $dbw->replace('page_restrictions', array(array('pr_page', 'pr_type')), array('pr_page' => $id, 'pr_type' => $action, 'pr_level' => $restrictions, 'pr_cascade' => 0, 'pr_expiry' => $encodedExpiry), __METHOD__);
            } else {
                $dbw->delete('page_restrictions', array('pr_page' => $id, 'pr_type' => $action), __METHOD__);
            }
        }
        # Insert a null revision
        $nullRevision = Revision::newNullRevision($dbw, $id, $comment, true);
        $nullRevId = $nullRevision->insertOn($dbw);
        # Update page record
        $dbw->update('page', array('page_touched' => $dbw->timestamp(), 'page_restrictions' => '', 'page_latest' => $nullRevId), array('page_id' => $id), 'Article::protect');
        # Update the protection log
        $log = new LogPage('protect');
        if ($protect) {
            $log->addEntry($modified ? 'modify' : 'protect', $wgTitle, trim($reason . " [{$updated}]{$expiry_description}"));
        } else {
            $log->addEntry('unprotect', $wgTitle, $reason);
        }
    }
    # End "changed" check
    return true;
}
Example #13
0
 /**
  * Update the article's restriction field, and leave a log entry.
  * This works for protection both existing and non-existing pages.
  *
  * @param array $limit set of restriction keys
  * @param $reason String
  * @param &$cascade Integer. Set to false if cascading protection isn't allowed.
  * @param array $expiry per restriction type expiration
  * @param $user User The user updating the restrictions
  * @return Status
  */
 public function doUpdateRestrictions(array $limit, array $expiry, &$cascade, $reason, User $user)
 {
     global $wgContLang, $wgCascadingRestrictionLevels;
     if (wfReadOnly()) {
         return Status::newFatal('readonlytext', wfReadOnlyReason());
     }
     $restrictionTypes = $this->mTitle->getRestrictionTypes();
     $id = $this->getId();
     if (!$cascade) {
         $cascade = false;
     }
     // Take this opportunity to purge out expired restrictions
     Title::purgeExpiredRestrictions();
     // @todo FIXME: Same limitations as described in ProtectionForm.php (line 37);
     // we expect a single selection, but the schema allows otherwise.
     $isProtected = false;
     $protect = false;
     $changed = false;
     $dbw = wfGetDB(DB_MASTER);
     foreach ($restrictionTypes as $action) {
         if (!isset($expiry[$action])) {
             $expiry[$action] = $dbw->getInfinity();
         }
         if (!isset($limit[$action])) {
             $limit[$action] = '';
         } elseif ($limit[$action] != '') {
             $protect = true;
         }
         // Get current restrictions on $action
         $current = implode('', $this->mTitle->getRestrictions($action));
         if ($current != '') {
             $isProtected = true;
         }
         if ($limit[$action] != $current) {
             $changed = true;
         } elseif ($limit[$action] != '') {
             // Only check expiry change if the action is actually being
             // protected, since expiry does nothing on an not-protected
             // action.
             if ($this->mTitle->getRestrictionExpiry($action) != $expiry[$action]) {
                 $changed = true;
             }
         }
     }
     if (!$changed && $protect && $this->mTitle->areRestrictionsCascading() != $cascade) {
         $changed = true;
     }
     // If nothing has changed, do nothing
     if (!$changed) {
         return Status::newGood();
     }
     if (!$protect) {
         // No protection at all means unprotection
         $revCommentMsg = 'unprotectedarticle';
         $logAction = 'unprotect';
     } elseif ($isProtected) {
         $revCommentMsg = 'modifiedarticleprotection';
         $logAction = 'modify';
     } else {
         $revCommentMsg = 'protectedarticle';
         $logAction = 'protect';
     }
     $encodedExpiry = array();
     $protectDescription = '';
     # Some bots may parse IRC lines, which are generated from log entries which contain plain
     # protect description text. Keep them in old format to avoid breaking compatibility.
     # TODO: Fix protection log to store structured description and format it on-the-fly.
     $protectDescriptionLog = '';
     foreach ($limit as $action => $restrictions) {
         $encodedExpiry[$action] = $dbw->encodeExpiry($expiry[$action]);
         if ($restrictions != '') {
             $protectDescriptionLog .= $wgContLang->getDirMark() . "[{$action}={$restrictions}] (";
             # $action is one of $wgRestrictionTypes = array( 'create', 'edit', 'move', 'upload' ).
             # All possible message keys are listed here for easier grepping:
             # * restriction-create
             # * restriction-edit
             # * restriction-move
             # * restriction-upload
             $actionText = wfMessage('restriction-' . $action)->inContentLanguage()->text();
             # $restrictions is one of $wgRestrictionLevels = array( '', 'autoconfirmed', 'sysop' ),
             # with '' filtered out. All possible message keys are listed below:
             # * protect-level-autoconfirmed
             # * protect-level-sysop
             $restrictionsText = wfMessage('protect-level-' . $restrictions)->inContentLanguage()->text();
             if ($encodedExpiry[$action] != 'infinity') {
                 $expiryText = wfMessage('protect-expiring', $wgContLang->timeanddate($expiry[$action], false, false), $wgContLang->date($expiry[$action], false, false), $wgContLang->time($expiry[$action], false, false))->inContentLanguage()->text();
             } else {
                 $expiryText = wfMessage('protect-expiry-indefinite')->inContentLanguage()->text();
             }
             if ($protectDescription !== '') {
                 $protectDescription .= wfMessage('word-separator')->inContentLanguage()->text();
             }
             $protectDescription .= wfMessage('protect-summary-desc')->params($actionText, $restrictionsText, $expiryText)->inContentLanguage()->text();
             $protectDescriptionLog .= $expiryText . ') ';
         }
     }
     $protectDescriptionLog = trim($protectDescriptionLog);
     if ($id) {
         // Protection of existing page
         if (!wfRunHooks('ArticleProtect', array(&$this, &$user, $limit, $reason))) {
             return Status::newGood();
         }
         // Only certain restrictions can cascade... Otherwise, users who cannot normally protect pages
         // could "protect" them by transcluding them on protected pages they are allowed to edit.
         $editrestriction = isset($limit['edit']) ? array($limit['edit']) : $this->mTitle->getRestrictions('edit');
         $cascadingRestrictionLevels = $wgCascadingRestrictionLevels;
         if (in_array('sysop', $cascadingRestrictionLevels)) {
             $cascadingRestrictionLevels[] = 'protect';
             // backwards compatibility
         }
         // The schema allows multiple restrictions
         if (!array_intersect($editrestriction, $cascadingRestrictionLevels)) {
             $cascade = false;
         }
         // Update restrictions table
         foreach ($limit as $action => $restrictions) {
             if ($restrictions != '') {
                 $dbw->replace('page_restrictions', array(array('pr_page', 'pr_type')), array('pr_page' => $id, 'pr_type' => $action, 'pr_level' => $restrictions, 'pr_cascade' => $cascade && $action == 'edit' ? 1 : 0, 'pr_expiry' => $encodedExpiry[$action]), __METHOD__);
             } else {
                 $dbw->delete('page_restrictions', array('pr_page' => $id, 'pr_type' => $action), __METHOD__);
             }
         }
         // Prepare a null revision to be added to the history
         $editComment = $wgContLang->ucfirst(wfMessage($revCommentMsg, $this->mTitle->getPrefixedText())->inContentLanguage()->text());
         if ($reason) {
             $editComment .= wfMessage('colon-separator')->inContentLanguage()->text() . $reason;
         }
         if ($protectDescription) {
             $editComment .= wfMessage('word-separator')->inContentLanguage()->text();
             $editComment .= wfMessage('parentheses')->params($protectDescription)->inContentLanguage()->text();
         }
         if ($cascade) {
             $editComment .= wfMessage('word-separator')->inContentLanguage()->text();
             $editComment .= wfMessage('brackets')->params(wfMessage('protect-summary-cascade')->inContentLanguage()->text())->inContentLanguage()->text();
         }
         // Insert a null revision
         $nullRevision = Revision::newNullRevision($dbw, $id, $editComment, true);
         $nullRevId = $nullRevision->insertOn($dbw);
         $latest = $this->getLatest();
         // Update page record
         $dbw->update('page', array('page_touched' => $dbw->timestamp(), 'page_restrictions' => '', 'page_latest' => $nullRevId), array('page_id' => $id), __METHOD__);
         wfRunHooks('NewRevisionFromEditComplete', array($this, $nullRevision, $latest, $user));
         wfRunHooks('ArticleProtectComplete', array(&$this, &$user, $limit, $reason));
     } else {
         // Protection of non-existing page (also known as "title protection")
         // Cascade protection is meaningless in this case
         $cascade = false;
         if ($limit['create'] != '') {
             $dbw->replace('protected_titles', array(array('pt_namespace', 'pt_title')), array('pt_namespace' => $this->mTitle->getNamespace(), 'pt_title' => $this->mTitle->getDBkey(), 'pt_create_perm' => $limit['create'], 'pt_timestamp' => $dbw->encodeExpiry(wfTimestampNow()), 'pt_expiry' => $encodedExpiry['create'], 'pt_user' => $user->getId(), 'pt_reason' => $reason), __METHOD__);
         } else {
             $dbw->delete('protected_titles', array('pt_namespace' => $this->mTitle->getNamespace(), 'pt_title' => $this->mTitle->getDBkey()), __METHOD__);
         }
     }
     $this->mTitle->flushRestrictions();
     InfoAction::invalidateCache($this->mTitle);
     if ($logAction == 'unprotect') {
         $logParams = array();
     } else {
         $logParams = array($protectDescriptionLog, $cascade ? 'cascade' : '');
     }
     // Update the protection log
     $log = new LogPage('protect');
     $log->addEntry($logAction, $this->mTitle, trim($reason), $logParams, $user);
     return Status::newGood();
 }
Example #14
0
 /**
  * Update the article's restriction field, and leave a log entry.
  *
  * @param array $limit set of restriction keys
  * @param string $reason
  * @return bool true on success
  */
 function updateRestrictions($limit = array(), $reason = '', $cascade = 0, $expiry = null)
 {
     global $wgUser, $wgRestrictionTypes, $wgContLang;
     $id = $this->mTitle->getArticleID();
     if (array() != $this->mTitle->getUserPermissionsErrors('protect', $wgUser) || wfReadOnly() || $id == 0) {
         return false;
     }
     if (!$cascade) {
         $cascade = false;
     }
     // Take this opportunity to purge out expired restrictions
     Title::purgeExpiredRestrictions();
     # FIXME: Same limitations as described in ProtectionForm.php (line 37);
     # we expect a single selection, but the schema allows otherwise.
     $current = array();
     foreach ($wgRestrictionTypes as $action) {
         $current[$action] = implode('', $this->mTitle->getRestrictions($action));
     }
     $current = Article::flattenRestrictions($current);
     $updated = Article::flattenRestrictions($limit);
     $changed = $current != $updated;
     $changed = $changed || $this->mTitle->areRestrictionsCascading() != $cascade;
     $changed = $changed || $this->mTitle->mRestrictionsExpiry != $expiry;
     $protect = $updated != '';
     # If nothing's changed, do nothing
     if ($changed) {
         global $wgGroupPermissions;
         if (wfRunHooks('ArticleProtect', array(&$this, &$wgUser, $limit, $reason))) {
             $dbw = wfGetDB(DB_MASTER);
             $encodedExpiry = Block::encodeExpiry($expiry, $dbw);
             $expiry_description = '';
             if ($encodedExpiry != 'infinity') {
                 $expiry_description = ' (' . wfMsgForContent('protect-expiring', $wgContLang->timeanddate($expiry, false, false)) . ')';
             }
             # Prepare a null revision to be added to the history
             $modified = $current != '' && $protect;
             if ($protect) {
                 $comment_type = $modified ? 'modifiedarticleprotection' : 'protectedarticle';
             } else {
                 $comment_type = 'unprotectedarticle';
             }
             $comment = $wgContLang->ucfirst(wfMsgForContent($comment_type, $this->mTitle->getPrefixedText()));
             foreach ($limit as $action => $restrictions) {
                 # Check if the group level required to edit also can protect pages
                 # Otherwise, people who cannot normally protect can "protect" pages via transclusion
                 $cascade = $cascade && isset($wgGroupPermissions[$restrictions]['protect']) && $wgGroupPermissions[$restrictions]['protect'];
             }
             $cascade_description = '';
             if ($cascade) {
                 $cascade_description = ' [' . wfMsg('protect-summary-cascade') . ']';
             }
             if ($reason) {
                 $comment .= ": {$reason}";
             }
             if ($protect) {
                 $comment .= " [{$updated}]";
             }
             if ($expiry_description && $protect) {
                 $comment .= "{$expiry_description}";
             }
             if ($cascade) {
                 $comment .= "{$cascade_description}";
             }
             $rowsAffected = false;
             # Update restrictions table
             foreach ($limit as $action => $restrictions) {
                 if ($restrictions != '') {
                     $dbw->replace('page_restrictions', array(array('pr_page', 'pr_type')), array('pr_page' => $id, 'pr_type' => $action, 'pr_level' => $restrictions, 'pr_cascade' => $cascade ? 1 : 0, 'pr_expiry' => $encodedExpiry), __METHOD__);
                     if ($dbw->affectedRows() != 0) {
                         $rowsAffected = true;
                     }
                 } else {
                     $dbw->delete('page_restrictions', array('pr_page' => $id, 'pr_type' => $action), __METHOD__);
                     if ($dbw->affectedRows() != 0) {
                         $rowsAffected = true;
                     }
                 }
             }
             if (!$rowsAffected) {
                 // No change
                 return true;
             }
             # Insert a null revision
             $nullRevision = Revision::newNullRevision($dbw, $id, $comment, true);
             $nullRevId = $nullRevision->insertOn($dbw);
             # Update page record
             $dbw->update('page', array('page_touched' => $dbw->timestamp(), 'page_restrictions' => '', 'page_catinfo' => $this->mTitle->getCategoryMask(), 'page_latest' => $nullRevId), array('page_id' => $id), 'Article::protect');
             wfRunHooks('ArticleProtectComplete', array(&$this, &$wgUser, $limit, $reason));
             # Update the protection log
             $log = new LogPage('protect');
             if ($protect) {
                 $log->addEntry($modified ? 'modify' : 'protect', $this->mTitle, trim($reason . " [{$updated}]{$cascade_description}{$expiry_description}"));
             } else {
                 $log->addEntry('unprotect', $this->mTitle, $reason);
             }
         }
         # End hook
     }
     # End "changed" check
     return true;
 }