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); }
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 ); }
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; }
/** * 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); } }
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); }
/** * 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); }
/** * 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; }
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; }
/** * 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; }
/** * 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(); } }
/** * 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; }
/** * 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; }
/** * @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; }
/** * 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__); } }
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(); } }
/** * 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); }); } }
/** * 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; }
/** * 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; }
/** * 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; }
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; }
/** * 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; }
/** * 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(); }
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; }
/** * 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; }
/** * 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); }