예제 #1
0
 public function execute()
 {
     $user = $this->getUser();
     if (!$user->isLoggedIn()) {
         $this->dieUsage('You must be logged-in to have a watchlist', 'notloggedin');
     }
     $params = $this->extractRequestParams();
     $title = Title::newFromText($params['title']);
     if (!$title || $title->getNamespace() < 0) {
         $this->dieUsageMsg(array('invalidtitle', $params['title']));
     }
     $res = array('title' => $title->getPrefixedText());
     if ($params['unwatch']) {
         $res['unwatched'] = '';
         $res['message'] = $this->msg('removedwatchtext', $title->getPrefixedText())->title($title)->parseAsBlock();
         $success = UnwatchAction::doUnwatch($title, $user);
     } else {
         $res['watched'] = '';
         $res['message'] = $this->msg('addedwatchtext', $title->getPrefixedText())->title($title)->parseAsBlock();
         $success = WatchAction::doWatch($title, $user);
     }
     if (!$success) {
         $this->dieUsageMsg('hookaborted');
     }
     $this->getResult()->addValue(null, $this->getModuleName(), $res);
 }
예제 #2
0
	public function execute() {
		$user = $this->getUser();
		if ( !$user->isLoggedIn() ) {
			$this->dieUsage( 'You must be logged-in to have a watchlist', 'notloggedin' );
		}
		if ( !$user->isAllowed( 'editmywatchlist' ) ) {
			$this->dieUsage( 'You don\'t have permission to edit your watchlist', 'permissiondenied' );
		}

		$params = $this->extractRequestParams();
		$title = Title::newFromText( $params['title'] );

		if ( !$title || $title->isExternal() || !$title->canExist() ) {
			$this->dieUsageMsg( array( 'invalidtitle', $params['title'] ) );
		}

		$res = array( 'title' => $title->getPrefixedText() );

		// Currently unnecessary, code to act as a safeguard against any change in current behavior of uselang
		// Copy from ApiParse
		$oldLang = null;
		if ( isset( $params['uselang'] ) && $params['uselang'] != $this->getContext()->getLanguage()->getCode() ) {
			$oldLang = $this->getContext()->getLanguage(); // Backup language
			$this->getContext()->setLanguage( Language::factory( $params['uselang'] ) );
		}

		if ( $params['unwatch'] ) {
			$res['unwatched'] = '';
			$res['message'] = $this->msg( 'removedwatchtext', $title->getPrefixedText() )->title( $title )->parseAsBlock();
			$status = UnwatchAction::doUnwatch( $title, $user );
		} else {
			$res['watched'] = '';
			$res['message'] = $this->msg( 'addedwatchtext', $title->getPrefixedText() )->title( $title )->parseAsBlock();
			$status = WatchAction::doWatch( $title, $user );
		}

		if ( !is_null( $oldLang ) ) {
			$this->getContext()->setLanguage( $oldLang ); // Reset language to $oldLang
		}

		if ( !$status->isOK() ) {
			$this->dieStatus( $status );
		}
		$this->getResult()->addValue( null, $this->getModuleName(), $res );
	}
예제 #3
0
 public function move($params)
 {
     global $wgUser;
     $currentUser = $wgUser;
     $wgUser = User::newFromId($this->createdBy);
     $currentPageName = $this->title->getText();
     if ($params['use_regex']) {
         $newPageName = preg_replace("/{$params['target_str']}/U", $params['replacement_str'], $currentPageName);
     } else {
         $newPageName = str_replace($params['target_str'], $params['replacement_str'], $currentPageName);
     }
     $newTitle = Title::newFromText($newPageName, $this->title->getNamespace());
     $result = $this->title->moveTo($newTitle, true, $params['edit_summary'], $params['create_redirect']);
     if ($result == true && $params['watch_page']) {
         WatchAction::doWatch($newTitle, $wgUser);
     }
     $wgUser = $currentUser;
     return $result;
 }
예제 #4
0
 /**
  * Adds a user to watchlists of all articles defined in the
  * global $wgAutoFollowWatchlist variable.
  * @param integer $iUserId The user's ID
  */
 public function addUserToDefaultWatchlistTask($iUserId)
 {
     global $wgAutoFollowWatchlist;
     if (!empty($wgAutoFollowWatchlist)) {
         $oUser = \User::newFromId($iUserId);
         $aWatchSuccess = $aWatchFail = [];
         foreach ($wgAutoFollowWatchlist as $sTitleText) {
             $oTitle = \Title::newFromText($sTitleText);
             if ($oTitle instanceof \Title) {
                 \WatchAction::doWatch($oTitle, $oUser);
                 $aWatchSuccess[] = $sTitleText;
             } else {
                 $aWatchFail[] = $sTitleText;
             }
         }
         if (count($aWatchFail) === 0) {
             $this->setFlag($oUser);
         }
         $this->logResults($oUser, $aWatchSuccess, $aWatchFail);
     }
 }
예제 #5
0
 function delete()
 {
     global $wgUser, $wgOut, $wgRequest;
     $confirm = $wgRequest->wasPosted() && $wgUser->matchEditToken($wgRequest->getVal('wpEditToken'));
     $reason = $wgRequest->getText('wpReason');
     # This code desperately needs to be totally rewritten
     # Check permissions
     $permission_errors = $this->mTitle->getUserPermissionsErrors('mv_delete_mvd', $wgUser);
     if (count($permission_errors) > 0) {
         $wgOut->showPermissionsErrorPage($permission_errors);
         return;
     }
     $wgOut->setPagetitle(wfMsg('confirmdelete'));
     # Better double-check that it hasn't been deleted yet!
     $dbw = wfGetDB(DB_MASTER);
     $conds = $this->mTitle->pageCond();
     $latest = $dbw->selectField('page', 'page_latest', $conds, __METHOD__);
     if ($latest === false) {
         $wgOut->showFatalError(wfMsg('cannotdelete'));
         return;
     }
     if ($confirm) {
         $this->doDelete($reason);
         if ($wgRequest->getCheck('wpWatch')) {
             WatchAction::doWatch($this->mTitle, $wgUser);
         } elseif ($this->mTitle->userIsWatching()) {
             WatchAction::doUnwatch($this->mTitle, $wgUser);
         }
         return;
     }
     // Generate deletion reason
     $hasHistory = false;
     $reason = $this->generateReason($hasHistory);
     // If the page has a history, insert a warning
     if ($hasHistory && !$confirm) {
         $skin = $wgUser->getSkin();
         $wgOut->addHTML('<strong>' . wfMsg('historywarning') . ' ' . $skin->historyLink() . '</strong>');
     }
     return $this->confirmDelete('', $reason);
 }
예제 #6
0
 /**
  * Add this page to $wgUser's watchlist
  *
  * This is safe to be called multiple times
  *
  * @return bool true on successful watch operation
  * @deprecated since 1.18
  */
 public function doWatch()
 {
     global $wgUser;
     wfDeprecated(__METHOD__, '1.18');
     return WatchAction::doWatch($this->getTitle(), $wgUser);
 }
예제 #7
0
 /**
  * Run a replaceText job
  * @return boolean success
  */
 function run()
 {
     wfProfileIn(__METHOD__);
     if (is_null($this->title)) {
         $this->error = "replaceText: Invalid title";
         wfProfileOut(__METHOD__);
         return false;
     }
     if (array_key_exists('move_page', $this->params)) {
         global $wgUser;
         $actual_user = $wgUser;
         $wgUser = User::newFromId($this->params['user_id']);
         $cur_page_name = $this->title->getText();
         if ($this->params['use_regex']) {
             $new_page_name = preg_replace("/" . $this->params['target_str'] . "/U", $this->params['replacement_str'], $cur_page_name);
         } else {
             $new_page_name = str_replace($this->params['target_str'], $this->params['replacement_str'], $cur_page_name);
         }
         $new_title = Title::newFromText($new_page_name, $this->title->getNamespace());
         $reason = $this->params['edit_summary'];
         $create_redirect = $this->params['create_redirect'];
         $this->title->moveTo($new_title, true, $reason, $create_redirect);
         if ($this->params['watch_page']) {
             if (class_exists('WatchAction')) {
                 // Class was added in MW 1.19
                 WatchAction::doWatch($new_title, $wgUser);
             } else {
                 Action::factory('watch', new WikiPage($new_title))->execute();
             }
         }
         $wgUser = $actual_user;
     } else {
         // WikiPage::getContent() replaced
         // Article::fetchContent() starting in MW 1.21.
         if (method_exists('WikiPage', 'getContent')) {
             if ($this->title->getContentModel() !== CONTENT_MODEL_WIKITEXT) {
                 $this->error = 'replaceText: Wiki page "' . $this->title->getPrefixedDBkey() . '" does not hold regular wikitext.';
                 wfProfileOut(__METHOD__);
                 return false;
             }
             $wikiPage = new WikiPage($this->title);
             // Is this check necessary?
             if (!$wikiPage) {
                 $this->error = 'replaceText: Wiki page not found for "' . $this->title->getPrefixedDBkey() . '."';
                 wfProfileOut(__METHOD__);
                 return false;
             }
             $article_text = $wikiPage->getContent()->getNativeData();
         } else {
             $article = new Article($this->title, 0);
             if (!$article) {
                 $this->error = 'replaceText: Article not found for "' . $this->title->getPrefixedDBkey() . '"';
                 wfProfileOut(__METHOD__);
                 return false;
             }
             $article_text = $article->fetchContent();
         }
         wfProfileIn(__METHOD__ . '-replace');
         $target_str = $this->params['target_str'];
         $replacement_str = $this->params['replacement_str'];
         // @todo FIXME eh?
         $num_matches;
         if ($this->params['use_regex']) {
             $new_text = preg_replace('/' . $target_str . '/U', $replacement_str, $article_text, -1, $num_matches);
         } else {
             $new_text = str_replace($target_str, $replacement_str, $article_text, $num_matches);
         }
         // If there's at least one replacement, modify the page,
         // using the passed-in edit summary.
         if ($num_matches > 0) {
             // Change global $wgUser variable to the one
             // specified by the job only for the extent of
             // this replacement.
             global $wgUser;
             $actual_user = $wgUser;
             $wgUser = User::newFromId($this->params['user_id']);
             $edit_summary = $this->params['edit_summary'];
             $flags = EDIT_MINOR;
             if ($wgUser->isAllowed('bot')) {
                 $flags |= EDIT_FORCE_BOT;
             }
             if (method_exists('WikiPage', 'getContent')) {
                 $new_content = new WikitextContent($new_text);
                 $wikiPage->doEditContent($new_content, $edit_summary, $flags);
             } else {
                 $article->doEdit($new_text, $edit_summary, $flags);
             }
             $wgUser = $actual_user;
         }
         wfProfileOut(__METHOD__ . '-replace');
     }
     wfProfileOut(__METHOD__);
     return true;
 }
예제 #8
0
 private function watchTitle(Title $title, User $user, array $params, $compatibilityMode = false)
 {
     if (!$title->isWatchable()) {
         return array('title' => $title->getPrefixedText(), 'watchable' => 0);
     }
     $res = array('title' => $title->getPrefixedText());
     if ($params['unwatch']) {
         $status = UnwatchAction::doUnwatch($title, $user);
         $res['unwatched'] = $status->isOK();
         if ($status->isOK()) {
             $res['message'] = $this->msg('removedwatchtext', $title->getPrefixedText())->title($title)->parseAsBlock();
         }
     } else {
         $status = WatchAction::doWatch($title, $user);
         $res['watched'] = $status->isOK();
         if ($status->isOK()) {
             $res['message'] = $this->msg('addedwatchtext', $title->getPrefixedText())->title($title)->parseAsBlock();
         }
     }
     if (!$status->isOK()) {
         if ($compatibilityMode) {
             $this->dieStatus($status);
         }
         $res['error'] = $this->getErrorFromStatus($status);
     }
     return $res;
 }
예제 #9
0
 /**
  * Really perform the upload. Stores the file in the local repo, watches
  * if necessary and runs the UploadComplete hook.
  *
  * @param $comment
  * @param $pageText
  * @param $watch
  * @param $user User
  *
  * @return Status indicating the whether the upload succeeded.
  */
 public function performUpload($comment, $pageText, $watch, $user)
 {
     wfProfileIn(__METHOD__);
     $status = $this->getLocalFile()->upload($this->mTempPath, $comment, $pageText, File::DELETE_SOURCE, $this->mFileProps, false, $user);
     if ($status->isGood()) {
         if ($watch) {
             WatchAction::doWatch($this->getLocalFile()->getTitle(), $user, WatchedItem::IGNORE_USER_RIGHTS);
         }
         wfRunHooks('UploadComplete', array(&$this));
     }
     wfProfileOut(__METHOD__);
     return $status;
 }
예제 #10
0
 /**
  * Commit the change of watch status
  */
 protected function commitWatch()
 {
     global $wgUser;
     if ($this->watchthis xor $this->mTitle->userIsWatching()) {
         $dbw = wfGetDB(DB_MASTER);
         $dbw->begin();
         if ($this->watchthis) {
             WatchAction::doWatch($this->mTitle, $wgUser);
         } else {
             WatchAction::doUnwatch($this->mTitle, $wgUser);
         }
         $dbw->commit();
     }
 }
예제 #11
0
 /**
  * Given the form data, actually implement a block. This is also called from ApiBlock.
  *
  * @param array $data
  * @param IContextSource $context
  * @return bool|string
  */
 public static function processForm(array $data, IContextSource $context)
 {
     global $wgBlockAllowsUTEdit, $wgHideUserContribLimit, $wgContLang;
     $performer = $context->getUser();
     // Handled by field validator callback
     // self::validateTargetField( $data['Target'] );
     # This might have been a hidden field or a checkbox, so interesting data
     # can come from it
     $data['Confirm'] = !in_array($data['Confirm'], array('', '0', null, false), true);
     /** @var User $target */
     list($target, $type) = self::getTargetAndType($data['Target']);
     if ($type == Block::TYPE_USER) {
         $user = $target;
         $target = $user->getName();
         $userId = $user->getId();
         # Give admins a heads-up before they go and block themselves.  Much messier
         # to do this for IPs, but it's pretty unlikely they'd ever get the 'block'
         # permission anyway, although the code does allow for it.
         # Note: Important to use $target instead of $data['Target']
         # since both $data['PreviousTarget'] and $target are normalized
         # but $data['target'] gets overridden by (non-normalized) request variable
         # from previous request.
         if ($target === $performer->getName() && ($data['PreviousTarget'] !== $target || !$data['Confirm'])) {
             return array('ipb-blockingself', 'ipb-confirmaction');
         }
     } elseif ($type == Block::TYPE_RANGE) {
         $userId = 0;
     } elseif ($type == Block::TYPE_IP) {
         $target = $target->getName();
         $userId = 0;
     } else {
         # This should have been caught in the form field validation
         return array('badipaddress');
     }
     if (strlen($data['Expiry']) == 0 || strlen($data['Expiry']) > 50 || !self::parseExpiryInput($data['Expiry'])) {
         return array('ipb_expiry_invalid');
     }
     if (!isset($data['DisableEmail'])) {
         $data['DisableEmail'] = false;
     }
     # If the user has done the form 'properly', they won't even have been given the
     # option to suppress-block unless they have the 'hideuser' permission
     if (!isset($data['HideUser'])) {
         $data['HideUser'] = false;
     }
     if ($data['HideUser']) {
         if (!$performer->isAllowed('hideuser')) {
             # this codepath is unreachable except by a malicious user spoofing forms,
             # or by race conditions (user has hideuser and block rights, loads block form,
             # and loses hideuser rights before submission); so need to fail completely
             # rather than just silently disable hiding
             return array('badaccess-group0');
         }
         # Recheck params here...
         if ($type != Block::TYPE_USER) {
             $data['HideUser'] = false;
             # IP users should not be hidden
         } elseif (!wfIsInfinity($data['Expiry'])) {
             # Bad expiry.
             return array('ipb_expiry_temp');
         } elseif ($wgHideUserContribLimit !== false && $user->getEditCount() > $wgHideUserContribLimit) {
             # Typically, the user should have a handful of edits.
             # Disallow hiding users with many edits for performance.
             return array(array('ipb_hide_invalid', Message::numParam($wgHideUserContribLimit)));
         } elseif (!$data['Confirm']) {
             return array('ipb-confirmhideuser', 'ipb-confirmaction');
         }
     }
     # Create block object.
     $block = new Block();
     $block->setTarget($target);
     $block->setBlocker($performer);
     # Truncate reason for whole multibyte characters
     $block->mReason = $wgContLang->truncate($data['Reason'][0], 255);
     $block->mExpiry = self::parseExpiryInput($data['Expiry']);
     $block->prevents('createaccount', $data['CreateAccount']);
     $block->prevents('editownusertalk', !$wgBlockAllowsUTEdit || $data['DisableUTEdit']);
     $block->prevents('sendemail', $data['DisableEmail']);
     $block->isHardblock($data['HardBlock']);
     $block->isAutoblocking($data['AutoBlock']);
     $block->mHideName = $data['HideUser'];
     $reason = array('hookaborted');
     if (!Hooks::run('BlockIp', array(&$block, &$performer, &$reason))) {
         return $reason;
     }
     # Try to insert block. Is there a conflicting block?
     $status = $block->insert();
     if (!$status) {
         # Indicates whether the user is confirming the block and is aware of
         # the conflict (did not change the block target in the meantime)
         $blockNotConfirmed = !$data['Confirm'] || array_key_exists('PreviousTarget', $data) && $data['PreviousTarget'] !== $target;
         # Special case for API - bug 32434
         $reblockNotAllowed = array_key_exists('Reblock', $data) && !$data['Reblock'];
         # Show form unless the user is already aware of this...
         if ($blockNotConfirmed || $reblockNotAllowed) {
             return array(array('ipb_already_blocked', $block->getTarget()));
             # Otherwise, try to update the block...
         } else {
             # This returns direct blocks before autoblocks/rangeblocks, since we should
             # be sure the user is blocked by now it should work for our purposes
             $currentBlock = Block::newFromTarget($target);
             if ($block->equals($currentBlock)) {
                 return array(array('ipb_already_blocked', $block->getTarget()));
             }
             # If the name was hidden and the blocking user cannot hide
             # names, then don't allow any block changes...
             if ($currentBlock->mHideName && !$performer->isAllowed('hideuser')) {
                 return array('cant-see-hidden-user');
             }
             $currentBlock->isHardblock($block->isHardblock());
             $currentBlock->prevents('createaccount', $block->prevents('createaccount'));
             $currentBlock->mExpiry = $block->mExpiry;
             $currentBlock->isAutoblocking($block->isAutoblocking());
             $currentBlock->mHideName = $block->mHideName;
             $currentBlock->prevents('sendemail', $block->prevents('sendemail'));
             $currentBlock->prevents('editownusertalk', $block->prevents('editownusertalk'));
             $currentBlock->mReason = $block->mReason;
             $status = $currentBlock->update();
             $logaction = 'reblock';
             # Unset _deleted fields if requested
             if ($currentBlock->mHideName && !$data['HideUser']) {
                 RevisionDeleteUser::unsuppressUserName($target, $userId);
             }
             # If hiding/unhiding a name, this should go in the private logs
             if ((bool) $currentBlock->mHideName) {
                 $data['HideUser'] = true;
             }
         }
     } else {
         $logaction = 'block';
     }
     Hooks::run('BlockIpComplete', array($block, $performer));
     # Set *_deleted fields if requested
     if ($data['HideUser']) {
         RevisionDeleteUser::suppressUserName($target, $userId);
     }
     # Can't watch a rangeblock
     if ($type != Block::TYPE_RANGE && $data['Watch']) {
         WatchAction::doWatch(Title::makeTitle(NS_USER, $target), $performer, WatchedItem::IGNORE_USER_RIGHTS);
     }
     # Block constructor sanitizes certain block options on insert
     $data['BlockEmail'] = $block->prevents('sendemail');
     $data['AutoBlock'] = $block->isAutoblocking();
     # Prepare log parameters
     $logParams = array();
     $logParams['5::duration'] = $data['Expiry'];
     $logParams['6::flags'] = self::blockLogFlags($data, $type);
     # Make log entry, if the name is hidden, put it in the suppression log
     $log_type = $data['HideUser'] ? 'suppress' : 'block';
     $logEntry = new ManualLogEntry($log_type, $logaction);
     $logEntry->setTarget(Title::makeTitle(NS_USER, $target));
     $logEntry->setComment($data['Reason'][0]);
     $logEntry->setPerformer($performer);
     $logEntry->setParameters($logParams);
     # Relate log ID to block IDs (bug 25763)
     $blockIds = array_merge(array($status['id']), $status['autoIds']);
     $logEntry->setRelations(array('ipb_id' => $blockIds));
     $logId = $logEntry->insert();
     $logEntry->publish($logId);
     # Report to the user
     return true;
 }
예제 #12
0
 /**
  * Really perform the upload. Stores the file in the local repo, watches
  * if necessary and runs the UploadComplete hook.
  *
  * @param string $comment
  * @param string $pageText
  * @param bool $watch Whether the file page should be added to user's watchlist.
  *   (This doesn't check $user's permissions.)
  * @param User $user
  * @param string[] $tags Change tags to add to the log entry and page revision.
  *   (This doesn't check $user's permissions.)
  * @return Status Indicating the whether the upload succeeded.
  */
 public function performUpload($comment, $pageText, $watch, $user, $tags = [])
 {
     $this->getLocalFile()->load(File::READ_LATEST);
     $props = $this->mFileProps;
     $error = null;
     Hooks::run('UploadVerifyUpload', [$this, $user, $props, $comment, $pageText, &$error]);
     if ($error) {
         if (!is_array($error)) {
             $error = [$error];
         }
         return call_user_func_array('Status::newFatal', $error);
     }
     $status = $this->getLocalFile()->upload($this->mTempPath, $comment, $pageText, File::DELETE_SOURCE, $props, false, $user, $tags);
     if ($status->isGood()) {
         if ($watch) {
             WatchAction::doWatch($this->getLocalFile()->getTitle(), $user, User::IGNORE_USER_RIGHTS);
         }
         Hooks::run('UploadComplete', [&$this]);
         $this->postProcessUpload();
     }
     return $status;
 }
예제 #13
0
 /**
  * @author Federico "Lox" Lucignano
  *
  * overrides TopListBase::save
  */
 public function save($mode = TOPLISTS_SAVE_AUTODETECT)
 {
     global $wgMemc, $wgUser;
     $errors = array();
     $mode = $this->_detectProcessingMode($mode);
     $checkResult = $this->checkForProcessing($mode);
     if ($checkResult === true) {
         $contentText = '';
         $relatedArticle = $this->getRelatedArticle();
         if (!empty($relatedArticle)) {
             $contentText .= ' ' . TOPLIST_ATTRIBUTE_RELATED . '="' . htmlspecialchars($relatedArticle->getPrefixedText()) . '"';
         }
         $picture = $this->getPicture();
         if (!empty($picture)) {
             $contentText .= ' ' . TOPLIST_ATTRIBUTE_PICTURE . '="' . htmlspecialchars($picture->getText()) . '"';
         }
         $description = $this->getDescription();
         if (!empty($description)) {
             $contentText .= ' ' . TOPLIST_ATTRIBUTE_DESCRIPTION . '="' . htmlspecialchars($description) . '"';
         }
         $contentText .= ' ' . TOPLIST_ATTRIBUTE_LASTUPDATE . '="' . wfTimestampNow() . '"';
         $summaryMsg = null;
         $editMode = null;
         if ($mode == TOPLISTS_SAVE_CREATE) {
             //$summaryMsg = 'toplists-list-creation-summary';
             $editMode = EDIT_NEW;
         } else {
             //$summaryMsg = 'toplists-list-update-summary';
             $editMode = EDIT_UPDATE;
         }
         $article = $this->getArticle();
         $status = $article->doEdit('<' . TOPLIST_TAG . "{$contentText} />[[Category:" . wfMsgForContent('toplists-category') . "]]", $this->_getItemsSummaryStatusMsg(), $editMode);
         if ($editMode == EDIT_NEW) {
             WatchAction::doWatch($article->mTitle, $wgUser);
         }
         if (!$status->isOK()) {
             foreach ($status->getErrorsArray() as $msg) {
                 $errors[] = array('msg' => $msg, 'params' => null);
             }
         } else {
             //reset vote counters for each items, to avoid caching issues
             foreach ($this->getItems(true) as $item) {
                 $item->resetVotesCount();
             }
             $wgMemc->set($this->_getNeedRefreshCacheKey(), true);
         }
     } else {
         $errors = array_merge($errors, $checkResult);
     }
     return empty($errors) ? true : $errors;
 }
예제 #14
0
 /**
  * Commit the change of watch status
  */
 protected function commitWatch()
 {
     global $wgUser;
     if ($wgUser->isLoggedIn() && $this->watchthis != $wgUser->isWatched($this->mTitle)) {
         $dbw = wfGetDB(DB_MASTER);
         $dbw->begin(__METHOD__);
         if ($this->watchthis) {
             WatchAction::doWatch($this->mTitle, $wgUser);
         } else {
             WatchAction::doUnwatch($this->mTitle, $wgUser);
         }
         $dbw->commit(__METHOD__);
     }
 }
예제 #15
0
        continue;
    }
    if ($user->getGlobalPreference('marketingallowed') != 1) {
        continue;
    }
    if (!$user->isEmailConfirmed()) {
        continue;
    }
    if ($user->getEditCount() == 0) {
        continue;
    }
    foreach ($textsToWatch[$wgLanguageCode] as $text) {
        $titlesToWatch[] = Title::newFromText($text);
    }
    $status = false;
    foreach ($titlesToWatch as $title) {
        $logParams = ['user_id' => $row['user_id'], 'user_name' => $user->getName(), 'user_lang' => $userLanguage, 'title' => $title->getPrefixedText()];
        if ($title instanceof Title) {
            WatchAction::doWatch($title, $user);
            $status = true;
            \Wikia\Logger\WikiaLogger::instance()->info("AutoFollow: User {$user->getName()} added to watchlist of {$title->getPrefixedText()}.", $logParams);
        } else {
            // Log error to check for typos etc. Can be deleted when tested in production enviroment.
            \Wikia\Logger\WikiaLogger::instance()->error("AutoFollow: Invalid article name in {$userLanguage}", $logParams);
        }
    }
    if ($status) {
        $user->setGlobalFlag($alreadyWatchedKey, 1);
        $user->saveSettings();
    }
}
예제 #16
0
 /**
  * Register the change of watch status
  */
 protected function updateWatchlist()
 {
     global $wgUser;
     if ($wgUser->isLoggedIn() && $this->watchthis != $wgUser->isWatched($this->mTitle)) {
         $fname = __METHOD__;
         $title = $this->mTitle;
         $watch = $this->watchthis;
         // Do this in its own transaction to reduce contention...
         $dbw = wfGetDB(DB_MASTER);
         $dbw->onTransactionIdle(function () use($dbw, $title, $watch, $wgUser, $fname) {
             $dbw->begin($fname);
             if ($watch) {
                 WatchAction::doWatch($title, $wgUser);
             } else {
                 WatchAction::doUnwatch($title, $wgUser);
             }
             $dbw->commit($fname);
         });
     }
 }
예제 #17
0
 /**
  * Really delete the file
  *
  * @param $title Title object
  * @param $file File object
  * @param $oldimage String: archive name
  * @param $reason String: reason of the deletion
  * @param $suppress Boolean: whether to mark all deleted versions as restricted
  */
 public static function doDelete(&$title, &$file, &$oldimage, $reason, $suppress)
 {
     global $wgUser;
     $article = null;
     $status = Status::newFatal('error');
     if ($oldimage) {
         $status = $file->deleteOld($oldimage, $reason, $suppress);
         if ($status->ok) {
             // Need to do a log item
             $log = new LogPage('delete');
             $logComment = wfMsgForContent('deletedrevision', $oldimage);
             if (trim($reason) != '') {
                 $logComment .= wfMsgForContent('colon-separator') . $reason;
             }
             $log->addEntry('delete', $title, $logComment);
         }
     } else {
         $id = $title->getArticleID(Title::GAID_FOR_UPDATE);
         $article = new Article($title);
         $dbw = wfGetDB(DB_MASTER);
         try {
             // delete the associated article first
             if ($article->doDeleteArticle($reason, $suppress, $id, false)) {
                 global $wgRequest;
                 if ($wgRequest->getCheck('wpWatch') && $wgUser->isLoggedIn()) {
                     WatchAction::doWatch($title, $wgUser);
                 } elseif ($title->userIsWatching()) {
                     WatchAction::doUnwatch($title, $wgUser);
                 }
                 $status = $file->delete($reason, $suppress);
                 if ($status->ok) {
                     $dbw->commit();
                 } else {
                     $dbw->rollback();
                 }
             }
         } catch (MWException $e) {
             // rollback before returning to prevent UI from displaying incorrect "View or restore N deleted edits?"
             $dbw->rollback();
             throw $e;
         }
     }
     if ($status->isGood()) {
         wfRunHooks('FileDeleteComplete', array(&$file, &$oldimage, &$article, &$wgUser, &$reason));
     }
     return $status;
 }
예제 #18
0
 /**
  * Save submitted protection form
  *
  * @return Boolean: success
  */
 function save()
 {
     global $wgRequest, $wgUser, $wgOut;
     # Permission check!
     if ($this->disabled) {
         $this->show();
         return false;
     }
     $token = $wgRequest->getVal('wpEditToken');
     if (!$wgUser->matchEditToken($token, array('protect', $this->mTitle->getPrefixedDBkey()))) {
         $this->show(array('sessionfailure'));
         return false;
     }
     # Create reason string. Use list and/or custom string.
     $reasonstr = $this->mReasonSelection;
     if ($reasonstr != 'other' && $this->mReason != '') {
         // Entry from drop down menu + additional comment
         $reasonstr .= wfMessage('colon-separator')->text() . $this->mReason;
     } elseif ($reasonstr == 'other') {
         $reasonstr = $this->mReason;
     }
     $expiry = array();
     foreach ($this->mApplicableTypes as $action) {
         $expiry[$action] = $this->getExpiry($action);
         if (empty($this->mRestrictions[$action])) {
             continue;
         }
         // unprotected
         if (!$expiry[$action]) {
             $this->show(array('protect_expiry_invalid'));
             return false;
         }
         if ($expiry[$action] < wfTimestampNow()) {
             $this->show(array('protect_expiry_old'));
             return false;
         }
     }
     # They shouldn't be able to do this anyway, but just to make sure, ensure that cascading restrictions aren't being applied
     #  to a semi-protected page.
     global $wgGroupPermissions;
     $edit_restriction = isset($this->mRestrictions['edit']) ? $this->mRestrictions['edit'] : '';
     $this->mCascade = $wgRequest->getBool('mwProtect-cascade');
     if ($this->mCascade && $edit_restriction != 'protect' && !(isset($wgGroupPermissions[$edit_restriction]['protect']) && $wgGroupPermissions[$edit_restriction]['protect'])) {
         $this->mCascade = false;
     }
     $status = $this->mArticle->doUpdateRestrictions($this->mRestrictions, $expiry, $this->mCascade, $reasonstr, $wgUser);
     if (!$status->isOK()) {
         $this->show($wgOut->parseInline($status->getWikiText()));
         return false;
     }
     /**
      * Give extensions a change to handle added form items
      *
      * @since 1.19 you can (and you should) return false to abort saving;
      *             you can also return an array of message name and its parameters
      */
     $errorMsg = '';
     if (!wfRunHooks('ProtectionForm::save', array($this->mArticle, &$errorMsg))) {
         if ($errorMsg == '') {
             $errorMsg = array('hookaborted');
         }
     }
     if ($errorMsg != '') {
         $this->show($errorMsg);
         return false;
     }
     if ($wgUser->isLoggedIn() && $wgRequest->getCheck('mwProtectWatch') != $wgUser->isWatched($this->mTitle)) {
         if ($wgRequest->getCheck('mwProtectWatch')) {
             WatchAction::doWatch($this->mTitle, $wgUser);
         } else {
             WatchAction::doUnwatch($this->mTitle, $wgUser);
         }
     }
     return true;
 }
예제 #19
0
 /**
  * Set a watch (or unwatch) based the based on a watchlist parameter.
  * @param $watch String Valid values: 'watch', 'unwatch', 'preferences', 'nochange'
  * @param $titleObj Title the article's title to change
  * @param $userOption String The user option to consider when $watch=preferences
  */
 protected function setWatch($watch, $titleObj, $userOption = null)
 {
     $value = $this->getWatchlistValue($watch, $titleObj, $userOption);
     if ($value === null) {
         return;
     }
     $user = $this->getUser();
     if ($value) {
         WatchAction::doWatch($titleObj, $user);
     } else {
         WatchAction::doUnwatch($titleObj, $user);
     }
 }
	/**
	 * Run a replaceText job
	 * @return boolean success
	 */
	function run() {
		wfProfileIn( __METHOD__ );

		if ( is_null( $this->title ) ) {
			$this->error = "replaceText: Invalid title";
			wfProfileOut( __METHOD__ );
			return false;
		}

		if ( array_key_exists( 'move_page', $this->params ) ) {
			global $wgUser;
			$actual_user = $wgUser;
			$wgUser = User::newFromId( $this->params['user_id'] );
			$cur_page_name = $this->title->getText();
			if ( $this->params['use_regex'] ) {
				$new_page_name = preg_replace( "/".$this->params['target_str']."/U", $this->params['replacement_str'], $cur_page_name );
			} else {
				$new_page_name = str_replace( $this->params['target_str'], $this->params['replacement_str'], $cur_page_name );
			}

			$new_title = Title::newFromText( $new_page_name, $this->title->getNamespace() );
			$reason = $this->params['edit_summary'];
			$create_redirect = $this->params['create_redirect'];
			$this->title->moveTo( $new_title, true, $reason, $create_redirect );
			if ( $this->params['watch_page'] ) {
				if ( class_exists( 'WatchAction' ) ) {
					// Class was added in MW 1.19
					WatchAction::doWatch( $new_title, $wgUser );
				} elseif ( class_exists( 'Action' ) ) {
					// Class was added in MW 1.18
					Action::factory( 'watch', new Article( $new_title, 0 ) )->execute();
				} else {
					$article = new Article( $new_title, 0 );
					$article->doWatch();
				}
			}
			$wgUser = $actual_user;
		} else {
			$article = new Article( $this->title, 0 );
			if ( !$article ) {
				$this->error = 'replaceText: Article not found "' . $this->title->getPrefixedDBkey() . '"';
				wfProfileOut( __METHOD__ );
				return false;
			}

			wfProfileIn( __METHOD__ . '-replace' );
			$article_text = $article->fetchContent();
			$target_str = $this->params['target_str'];
			$replacement_str = $this->params['replacement_str'];
			$num_matches;

			if ( $this->params['use_regex'] ) {
				$new_text = preg_replace( '/'.$target_str.'/U', $replacement_str, $article_text, -1, $num_matches );
			} else {
				$new_text = str_replace( $target_str, $replacement_str, $article_text, $num_matches );
			}

			// if there's at least one replacement, modify the page,
			// using the passed-in edit summary
			if ( $num_matches > 0 ) {
				// change global $wgUser variable to the one
				// specified by the job only for the extent of
				// this replacement
				global $wgUser;
				$actual_user = $wgUser;
				$wgUser = User::newFromId( $this->params['user_id'] );
				$edit_summary = $this->params['edit_summary'];
				$flags = EDIT_MINOR;
				if ( $wgUser->isAllowed( 'bot' ) )
					$flags |= EDIT_FORCE_BOT;
				$article->doEdit( $new_text, $edit_summary, $flags );
				$wgUser = $actual_user;
			}
			wfProfileOut( __METHOD__ . '-replace' );
		}
		wfProfileOut( __METHOD__ );
		return true;
	}
예제 #21
0
 private function watchTitle(Title $title, User $user, array $params, $compatibilityMode = false)
 {
     if (!$title->isWatchable()) {
         return array('title' => $title->getPrefixedText(), 'watchable' => 0);
     }
     $res = array('title' => $title->getPrefixedText());
     // Currently unnecessary, code to act as a safeguard against any change
     // in current behavior of uselang.
     // Copy from ApiParse
     $oldLang = null;
     if (isset($params['uselang']) && $params['uselang'] != $this->getContext()->getLanguage()->getCode()) {
         $oldLang = $this->getContext()->getLanguage();
         // Backup language
         $this->getContext()->setLanguage(Language::factory($params['uselang']));
     }
     if ($params['unwatch']) {
         $status = UnwatchAction::doUnwatch($title, $user);
         if ($status->isOK()) {
             $res['unwatched'] = '';
             $res['message'] = $this->msg('removedwatchtext', $title->getPrefixedText())->title($title)->parseAsBlock();
         }
     } else {
         $status = WatchAction::doWatch($title, $user);
         if ($status->isOK()) {
             $res['watched'] = '';
             $res['message'] = $this->msg('addedwatchtext', $title->getPrefixedText())->title($title)->parseAsBlock();
         }
     }
     if (!is_null($oldLang)) {
         $this->getContext()->setLanguage($oldLang);
         // Reset language to $oldLang
     }
     if (!$status->isOK()) {
         if ($compatibilityMode) {
             $this->dieStatus($status);
         }
         $res['error'] = $this->getErrorFromStatus($status);
     }
     return $res;
 }
예제 #22
0
 /**
  * Save submitted protection form
  *
  * @return Boolean: success
  */
 function save()
 {
     global $wgRequest, $wgUser;
     # Permission check!
     if ($this->disabled) {
         $this->show();
         return false;
     }
     $token = $wgRequest->getVal('wpEditToken');
     if (!$wgUser->matchEditToken($token)) {
         $this->show(wfMsg('sessionfailure'));
         return false;
     }
     # Create reason string. Use list and/or custom string.
     $reasonstr = $this->mReasonSelection;
     if ($reasonstr != 'other' && $this->mReason != '') {
         // Entry from drop down menu + additional comment
         $reasonstr .= wfMsgForContent('colon-separator') . $this->mReason;
     } elseif ($reasonstr == 'other') {
         $reasonstr = $this->mReason;
     }
     $expiry = array();
     foreach ($this->mApplicableTypes as $action) {
         $expiry[$action] = $this->getExpiry($action);
         if (empty($this->mRestrictions[$action])) {
             continue;
         }
         // unprotected
         if (!$expiry[$action]) {
             $this->show(wfMsg('protect_expiry_invalid'));
             return false;
         }
         if ($expiry[$action] < wfTimestampNow()) {
             $this->show(wfMsg('protect_expiry_old'));
             return false;
         }
     }
     # They shouldn't be able to do this anyway, but just to make sure, ensure that cascading restrictions aren't being applied
     #  to a semi-protected page.
     global $wgGroupPermissions;
     $edit_restriction = isset($this->mRestrictions['edit']) ? $this->mRestrictions['edit'] : '';
     $this->mCascade = $wgRequest->getBool('mwProtect-cascade');
     if ($this->mCascade && $edit_restriction != 'protect' && !(isset($wgGroupPermissions[$edit_restriction]['protect']) && $wgGroupPermissions[$edit_restriction]['protect'])) {
         $this->mCascade = false;
     }
     if ($this->mTitle->exists()) {
         $ok = $this->mArticle->updateRestrictions($this->mRestrictions, $reasonstr, $this->mCascade, $expiry);
     } else {
         $ok = $this->mTitle->updateTitleProtection($this->mRestrictions['create'], $reasonstr, $expiry['create']);
     }
     if (!$ok) {
         throw new FatalError("Unknown error at restriction save time.");
     }
     $errorMsg = '';
     # Give extensions a change to handle added form items
     if (!wfRunHooks('ProtectionForm::save', array($this->mArticle, &$errorMsg))) {
         throw new FatalError("Unknown hook error at restriction save time.");
     }
     if ($errorMsg != '') {
         $this->show($errorMsg);
         return false;
     }
     if ($wgRequest->getCheck('mwProtectWatch') && $wgUser->isLoggedIn()) {
         WatchAction::doWatch($this->mTitle, $wgUser);
     } elseif ($this->mTitle->userIsWatching()) {
         WatchAction::doUnwatch($this->mTitle, $wgUser);
     }
     return $ok;
 }
예제 #23
0
 /**
  * Add this page to the current user's watchlist
  *
  * This is safe to be called multiple times
  *
  * @return bool true on successful watch operation
  * @deprecated since 1.18
  */
 public function doWatch()
 {
     wfDeprecated(__METHOD__, '1.18');
     return WatchAction::doWatch($this->getTitle(), $this->getContext()->getUser());
 }
 /**
  * Fulfil the request; shows the form or deletes the file,
  * pending authentication, confirmation, etc.
  */
 public function execute()
 {
     global $wgOut, $wgRequest, $wgUser, $wgUploadMaintenance;
     $permissionErrors = $this->title->getUserPermissionsErrors('delete', $wgUser);
     if (count($permissionErrors)) {
         throw new PermissionsError('delete', $permissionErrors);
     }
     if (wfReadOnly()) {
         throw new ReadOnlyError();
     }
     if ($wgUploadMaintenance) {
         throw new ErrorPageError('filedelete-maintenance-title', 'filedelete-maintenance');
     }
     $this->setHeaders();
     $this->oldimage = $wgRequest->getText('oldimage', false);
     $token = $wgRequest->getText('wpEditToken');
     # Flag to hide all contents of the archived revisions
     $suppress = $wgRequest->getVal('wpSuppress') && $wgUser->isAllowed('suppressrevision');
     if ($this->oldimage) {
         $this->oldfile = RepoGroup::singleton()->getLocalRepo()->newFromArchiveName($this->title, $this->oldimage);
     }
     if (!self::haveDeletableFile($this->file, $this->oldfile, $this->oldimage)) {
         $wgOut->addHTML($this->prepareMessage('filedelete-nofile'));
         $wgOut->addReturnTo($this->title);
         return;
     }
     // Perform the deletion if appropriate
     if ($wgRequest->wasPosted() && $wgUser->matchEditToken($token, $this->oldimage)) {
         $deleteReasonList = $wgRequest->getText('wpDeleteReasonList');
         $deleteReason = $wgRequest->getText('wpReason');
         if ($deleteReasonList == 'other') {
             $reason = $deleteReason;
         } elseif ($deleteReason != '') {
             // Entry from drop down menu + additional comment
             $reason = $deleteReasonList . wfMessage('colon-separator')->inContentLanguage()->text() . $deleteReason;
         } else {
             $reason = $deleteReasonList;
         }
         $status = self::doDelete($this->title, $this->file, $this->oldimage, $reason, $suppress, $wgUser);
         if (!$status->isGood()) {
             $wgOut->addHTML('<h2>' . $this->prepareMessage('filedeleteerror-short') . "</h2>\n");
             $wgOut->addWikiText('<div class="error">' . $status->getWikiText('filedeleteerror-short', 'filedeleteerror-long') . '</div>');
         }
         if ($status->ok) {
             $wgOut->setPageTitle(wfMessage('actioncomplete'));
             $wgOut->addHTML($this->prepareMessage('filedelete-success'));
             // Return to the main page if we just deleted all versions of the
             // file, otherwise go back to the description page
             $wgOut->addReturnTo($this->oldimage ? $this->title : Title::newMainPage());
             if ($wgUser->isLoggedIn() && $wgRequest->getCheck('wpWatch') != $wgUser->isWatched($this->title)) {
                 if ($wgRequest->getCheck('wpWatch')) {
                     WatchAction::doWatch($this->title, $wgUser);
                 } else {
                     WatchAction::doUnwatch($this->title, $wgUser);
                 }
             }
         }
         return;
     }
     $this->showForm();
     $this->showLogEntries();
 }
예제 #25
0
 static function create($root, $article, $superthread = null, $type = Threads::TYPE_NORMAL, $subject = '', $summary = '', $bump = null, $signature = null)
 {
     $thread = new Thread(null);
     if (!in_array($type, self::$VALID_TYPES)) {
         throw new MWException(__METHOD__ . ": invalid change type {$type}.");
     }
     if ($superthread) {
         $change_type = Threads::CHANGE_REPLY_CREATED;
     } else {
         $change_type = Threads::CHANGE_NEW_THREAD;
     }
     global $wgUser;
     $thread->setAuthor($wgUser);
     if (is_object($root)) {
         $thread->setRoot($root);
     } else {
         $thread->setRootId($root);
     }
     $thread->setSuperthread($superthread);
     $thread->setArticle($article);
     $thread->setSubject($subject);
     $thread->setType($type);
     if (!is_null($signature)) {
         $thread->setSignature($signature);
     }
     $thread->insert();
     if ($superthread) {
         $superthread->addReply($thread);
         $superthread->commitRevision($change_type, $thread, $summary, $bump);
     } else {
         $hthread = ThreadRevision::create($thread, $change_type);
     }
     // Create talk page
     Threads::createTalkpageIfNeeded($article);
     // Notifications
     NewMessages::writeMessageStateForUpdatedThread($thread, $change_type, $wgUser);
     if ($wgUser->getOption('lqt-watch-threads', false)) {
         WatchAction::doWatch($thread->topmostThread()->root()->getTitle(), $wgUser);
     }
     return $thread;
 }
예제 #26
0
 /**
  * Really perform the upload. Stores the file in the local repo, watches
  * if necessary and runs the UploadComplete hook.
  *
  * @param string $comment
  * @param string $pageText
  * @param bool $watch
  * @param User $user
  *
  * @return Status Indicating the whether the upload succeeded.
  */
 public function performUpload($comment, $pageText, $watch, $user)
 {
     $this->getLocalFile()->load(File::READ_LATEST);
     $status = $this->getLocalFile()->upload($this->mTempPath, $comment, $pageText, File::DELETE_SOURCE, $this->mFileProps, false, $user);
     if ($status->isGood()) {
         if ($watch) {
             WatchAction::doWatch($this->getLocalFile()->getTitle(), $user, WatchedItem::IGNORE_USER_RIGHTS);
         }
         Hooks::run('UploadComplete', array(&$this));
         $this->postProcessUpload();
     }
     return $status;
 }
 /**
  * UserLoginComplete hook handler
  * @see https://www.mediawiki.org/wiki/Manual:Hooks/UserLoginComplete
  *
  * Used here to handle watchlist actions made by anons to be handled after
  * login or account creation.
  *
  * @param User $currentUser
  * @param string $injected_html
  * @return bool
  */
 public static function onUserLoginComplete(&$currentUser, &$injected_html)
 {
     $context = MobileContext::singleton();
     if (!$context->shouldDisplayMobileView()) {
         return true;
     }
     // If 'watch' is set from the login form, watch the requested article
     $watch = $context->getRequest()->getVal('watch');
     if (!is_null($watch)) {
         $title = Title::newFromText($watch);
         // protect against watching special pages (these cannot be watched!)
         if (!is_null($title) && !$title->isSpecialPage()) {
             WatchAction::doWatch($title, $currentUser);
         }
     }
     return true;
 }
예제 #28
0
 /**
  * Add this page to $wgUser's watchlist
  *
  * This is safe to be called multiple times
  *
  * @return bool true on successful watch operation
  * @deprecated since 1.18
  */
 public function doWatch()
 {
     global $wgUser;
     return WatchAction::doWatch($this->getTitle(), $wgUser);
 }