Exemplo n.º 1
0
 public function execute()
 {
     global $wgUser;
     if (!$wgUser->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']));
     }
     $article = new Article($title, 0);
     $res = array('title' => $title->getPrefixedText());
     if ($params['unwatch']) {
         $res['unwatched'] = '';
         $res['message'] = wfMsgExt('removedwatchtext', array('parse'), $title->getPrefixedText());
         $success = WatchAction::doUnwatch($title, $wgUser);
     } else {
         $res['watched'] = '';
         $res['message'] = wfMsgExt('addedwatchtext', array('parse'), $title->getPrefixedText());
         $success = UnwatchAction::doWatch($title, $wgUser);
     }
     if (!$success) {
         $this->dieUsageMsg('hookaborted');
     }
     $this->getResult()->addValue(null, $this->getModuleName(), $res);
 }
Exemplo n.º 2
0
 /**
  * @param $skin Skin
  * @param $result
  * @return string
  */
 function formatResult($skin, $result)
 {
     global $wgContLang;
     $nt = Title::makeTitle($result->namespace, $result->title);
     $text = $wgContLang->convert($nt->getPrefixedText());
     $plink = Linker::linkKnown($nt, htmlspecialchars($text));
     $token = WatchAction::getWatchToken($nt, $this->getUser());
     $wlink = Linker::linkKnown($nt, wfMsgHtml('watch'), array(), array('action' => 'watch', 'token' => $token));
     return $this->getLanguage()->specialList($plink, $wlink);
 }
 /**
  * @param Skin $skin
  * @param object $result Result row
  * @return string
  */
 function formatResult($skin, $result)
 {
     global $wgContLang;
     $nt = Title::makeTitleSafe($result->namespace, $result->title);
     if (!$nt) {
         return Html::element('span', array('class' => 'mw-invalidtitle'), Linker::getInvalidTitleDescription($this->getContext(), $result->namespace, $result->title));
     }
     $text = $wgContLang->convert($nt->getPrefixedText());
     $plink = Linker::linkKnown($nt, htmlspecialchars($text));
     $token = WatchAction::getWatchToken($nt, $this->getUser());
     $wlink = Linker::linkKnown($nt, $this->msg('watch')->escaped(), array(), array('action' => 'watch', 'token' => $token));
     return $this->getLanguage()->specialList($plink, $wlink);
 }
Exemplo n.º 4
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 );
	}
Exemplo n.º 5
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;
 }
Exemplo n.º 6
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);
     }
 }
Exemplo n.º 7
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);
 }
Exemplo n.º 8
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;
 }
Exemplo n.º 9
0
 /**
  * a structured array of links usually used for the tabs in a skin
  *
  * There are 4 standard sections
  * namespaces: Used for namespace tabs like special, page, and talk namespaces
  * views: Used for primary page views like read, edit, history
  * actions: Used for most extra page actions like deletion, protection, etc...
  * variants: Used to list the language variants for the page
  *
  * Each section's value is a key/value array of links for that section.
  * The links themselves have these common keys:
  * - class: The css classes to apply to the tab
  * - text: The text to display on the tab
  * - href: The href for the tab to point to
  * - rel: An optional rel= for the tab's link
  * - redundant: If true the tab will be dropped in skins using content_actions
  *   this is useful for tabs like "Read" which only have meaning in skins that
  *   take special meaning from the grouped structure of content_navigation
  *
  * Views also have an extra key which can be used:
  * - primary: If this is not true skins like vector may try to hide the tab
  *            when the user has limited space in their browser window
  *
  * content_navigation using code also expects these ids to be present on the
  * links, however these are usually automatically generated by SkinTemplate
  * itself and are not necessary when using a hook. The only things these may
  * matter to are people modifying content_navigation after it's initial creation:
  * - id: A "preferred" id, most skins are best off outputting this preferred
  *   id for best compatibility.
  * - tooltiponly: This is set to true for some tabs in cases where the system
  *   believes that the accesskey should not be added to the tab.
  *
  * @return array
  */
 protected function buildContentNavigationUrls()
 {
     global $wgDisableLangConversion;
     // Display tabs for the relevant title rather than always the title itself
     $title = $this->getRelevantTitle();
     $onPage = $title->equals($this->getTitle());
     $out = $this->getOutput();
     $request = $this->getRequest();
     $user = $this->getUser();
     $content_navigation = array('namespaces' => array(), 'views' => array(), 'actions' => array(), 'variants' => array());
     // parameters
     $action = $request->getVal('action', 'view');
     $userCanRead = $title->quickUserCan('read', $user);
     $preventActiveTabs = false;
     Hooks::run('SkinTemplatePreventOtherActiveTabs', array(&$this, &$preventActiveTabs));
     // Checks if page is some kind of content
     if ($title->canExist()) {
         // Gets page objects for the related namespaces
         $subjectPage = $title->getSubjectPage();
         $talkPage = $title->getTalkPage();
         // Determines if this is a talk page
         $isTalk = $title->isTalkPage();
         // Generates XML IDs from namespace names
         $subjectId = $title->getNamespaceKey('');
         if ($subjectId == 'main') {
             $talkId = 'talk';
         } else {
             $talkId = "{$subjectId}_talk";
         }
         $skname = $this->skinname;
         // Adds namespace links
         $subjectMsg = array("nstab-{$subjectId}");
         if ($subjectPage->isMainPage()) {
             array_unshift($subjectMsg, 'mainpage-nstab');
         }
         $content_navigation['namespaces'][$subjectId] = $this->tabAction($subjectPage, $subjectMsg, !$isTalk && !$preventActiveTabs, '', $userCanRead);
         $content_navigation['namespaces'][$subjectId]['context'] = 'subject';
         $content_navigation['namespaces'][$talkId] = $this->tabAction($talkPage, array("nstab-{$talkId}", 'talk'), $isTalk && !$preventActiveTabs, '', $userCanRead);
         $content_navigation['namespaces'][$talkId]['context'] = 'talk';
         if ($userCanRead) {
             $isForeignFile = $title->inNamespace(NS_FILE) && $this->canUseWikiPage() && $this->getWikiPage() instanceof WikiFilePage && !$this->getWikiPage()->isLocal();
             // Adds view view link
             if ($title->exists() || $isForeignFile) {
                 $content_navigation['views']['view'] = $this->tabAction($isTalk ? $talkPage : $subjectPage, array("{$skname}-view-view", 'view'), $onPage && ($action == 'view' || $action == 'purge'), '', true);
                 // signal to hide this from simple content_actions
                 $content_navigation['views']['view']['redundant'] = true;
             }
             // If it is a non-local file, show a link to the file in its own repository
             if ($isForeignFile) {
                 $file = $this->getWikiPage()->getFile();
                 $content_navigation['views']['view-foreign'] = array('class' => '', 'text' => wfMessageFallback("{$skname}-view-foreign", 'view-foreign')->setContext($this->getContext())->params($file->getRepo()->getDisplayName())->text(), 'href' => $file->getDescriptionUrl(), 'primary' => false);
             }
             // Checks if user can edit the current page if it exists or create it otherwise
             if ($title->quickUserCan('edit', $user) && ($title->exists() || $title->quickUserCan('create', $user))) {
                 // Builds CSS class for talk page links
                 $isTalkClass = $isTalk ? ' istalk' : '';
                 // Whether the user is editing the page
                 $isEditing = $onPage && ($action == 'edit' || $action == 'submit');
                 // Whether to show the "Add a new section" tab
                 // Checks if this is a current rev of talk page and is not forced to be hidden
                 $showNewSection = !$out->forceHideNewSectionLink() && ($isTalk && $this->isRevisionCurrent() || $out->showNewSectionLink());
                 $section = $request->getVal('section');
                 if ($title->exists() || $title->getNamespace() == NS_MEDIAWIKI && $title->getDefaultMessageText() !== false) {
                     $msgKey = $isForeignFile ? 'edit-local' : 'edit';
                 } else {
                     $msgKey = $isForeignFile ? 'create-local' : 'create';
                 }
                 $content_navigation['views']['edit'] = array('class' => ($isEditing && ($section !== 'new' || !$showNewSection) ? 'selected' : '') . $isTalkClass, 'text' => wfMessageFallback("{$skname}-view-{$msgKey}", $msgKey)->setContext($this->getContext())->text(), 'href' => $title->getLocalURL($this->editUrlOptions()), 'primary' => !$isForeignFile);
                 // section link
                 if ($showNewSection) {
                     // Adds new section link
                     //$content_navigation['actions']['addsection']
                     $content_navigation['views']['addsection'] = array('class' => $isEditing && $section == 'new' ? 'selected' : false, 'text' => wfMessageFallback("{$skname}-action-addsection", 'addsection')->setContext($this->getContext())->text(), 'href' => $title->getLocalURL('action=edit&section=new'));
                 }
                 // Checks if the page has some kind of viewable content
             } elseif ($title->hasSourceText()) {
                 // Adds view source view link
                 $content_navigation['views']['viewsource'] = array('class' => $onPage && $action == 'edit' ? 'selected' : false, 'text' => wfMessageFallback("{$skname}-action-viewsource", 'viewsource')->setContext($this->getContext())->text(), 'href' => $title->getLocalURL($this->editUrlOptions()), 'primary' => true);
             }
             // Checks if the page exists
             if ($title->exists()) {
                 // Adds history view link
                 $content_navigation['views']['history'] = array('class' => $onPage && $action == 'history' ? 'selected' : false, 'text' => wfMessageFallback("{$skname}-view-history", 'history_short')->setContext($this->getContext())->text(), 'href' => $title->getLocalURL('action=history'));
                 if ($title->quickUserCan('delete', $user)) {
                     $content_navigation['actions']['delete'] = array('class' => $onPage && $action == 'delete' ? 'selected' : false, 'text' => wfMessageFallback("{$skname}-action-delete", 'delete')->setContext($this->getContext())->text(), 'href' => $title->getLocalURL('action=delete'));
                 }
                 if ($title->quickUserCan('move', $user)) {
                     $moveTitle = SpecialPage::getTitleFor('Movepage', $title->getPrefixedDBkey());
                     $content_navigation['actions']['move'] = array('class' => $this->getTitle()->isSpecial('Movepage') ? 'selected' : false, 'text' => wfMessageFallback("{$skname}-action-move", 'move')->setContext($this->getContext())->text(), 'href' => $moveTitle->getLocalURL());
                 }
             } else {
                 // article doesn't exist or is deleted
                 if ($user->isAllowed('deletedhistory')) {
                     $n = $title->isDeleted();
                     if ($n) {
                         $undelTitle = SpecialPage::getTitleFor('Undelete', $title->getPrefixedDBkey());
                         // If the user can't undelete but can view deleted
                         // history show them a "View .. deleted" tab instead.
                         $msgKey = $user->isAllowed('undelete') ? 'undelete' : 'viewdeleted';
                         $content_navigation['actions']['undelete'] = array('class' => $this->getTitle()->isSpecial('Undelete') ? 'selected' : false, 'text' => wfMessageFallback("{$skname}-action-{$msgKey}", "{$msgKey}_short")->setContext($this->getContext())->numParams($n)->text(), 'href' => $undelTitle->getLocalURL());
                     }
                 }
             }
             if ($title->quickUserCan('protect', $user) && $title->getRestrictionTypes() && MWNamespace::getRestrictionLevels($title->getNamespace(), $user) !== array('')) {
                 $mode = $title->isProtected() ? 'unprotect' : 'protect';
                 $content_navigation['actions'][$mode] = array('class' => $onPage && $action == $mode ? 'selected' : false, 'text' => wfMessageFallback("{$skname}-action-{$mode}", $mode)->setContext($this->getContext())->text(), 'href' => $title->getLocalURL("action={$mode}"));
             }
             // Checks if the user is logged in
             if ($this->loggedin && $user->isAllowedAll('viewmywatchlist', 'editmywatchlist')) {
                 /**
                  * The following actions use messages which, if made particular to
                  * the any specific skins, would break the Ajax code which makes this
                  * action happen entirely inline. OutputPage::getJSVars
                  * defines a set of messages in a javascript object - and these
                  * messages are assumed to be global for all skins. Without making
                  * a change to that procedure these messages will have to remain as
                  * the global versions.
                  */
                 $mode = $user->isWatched($title) ? 'unwatch' : 'watch';
                 $token = WatchAction::getWatchToken($title, $user, $mode);
                 $content_navigation['actions'][$mode] = array('class' => $onPage && ($action == 'watch' || $action == 'unwatch') ? 'selected' : false, 'text' => $this->msg($mode)->text(), 'href' => $title->getLocalURL(array('action' => $mode, 'token' => $token)));
             }
         }
         Hooks::run('SkinTemplateNavigation', array(&$this, &$content_navigation));
         if ($userCanRead && !$wgDisableLangConversion) {
             $pageLang = $title->getPageLanguage();
             // Gets list of language variants
             $variants = $pageLang->getVariants();
             // Checks that language conversion is enabled and variants exist
             // And if it is not in the special namespace
             if (count($variants) > 1) {
                 // Gets preferred variant (note that user preference is
                 // only possible for wiki content language variant)
                 $preferred = $pageLang->getPreferredVariant();
                 if (Action::getActionName($this) === 'view') {
                     $params = $request->getQueryValues();
                     unset($params['title']);
                 } else {
                     $params = array();
                 }
                 // Loops over each variant
                 foreach ($variants as $code) {
                     // Gets variant name from language code
                     $varname = $pageLang->getVariantname($code);
                     // Appends variant link
                     $content_navigation['variants'][] = array('class' => $code == $preferred ? 'selected' : false, 'text' => $varname, 'href' => $title->getLocalURL(array('variant' => $code) + $params), 'lang' => wfBCP47($code), 'hreflang' => wfBCP47($code));
                 }
             }
         }
     } else {
         // If it's not content, it's got to be a special page
         $content_navigation['namespaces']['special'] = array('class' => 'selected', 'text' => $this->msg('nstab-special')->text(), 'href' => $request->getRequestURL(), 'context' => 'subject');
         Hooks::run('SkinTemplateNavigation::SpecialPage', array(&$this, &$content_navigation));
     }
     // Equiv to SkinTemplateContentActions
     Hooks::run('SkinTemplateNavigation::Universal', array(&$this, &$content_navigation));
     // Setup xml ids and tooltip info
     foreach ($content_navigation as $section => &$links) {
         foreach ($links as $key => &$link) {
             $xmlID = $key;
             if (isset($link['context']) && $link['context'] == 'subject') {
                 $xmlID = 'ca-nstab-' . $xmlID;
             } elseif (isset($link['context']) && $link['context'] == 'talk') {
                 $xmlID = 'ca-talk';
             } elseif ($section == 'variants') {
                 $xmlID = 'ca-varlang-' . $xmlID;
             } else {
                 $xmlID = 'ca-' . $xmlID;
             }
             $link['id'] = $xmlID;
         }
     }
     # We don't want to give the watch tab an accesskey if the
     # page is being edited, because that conflicts with the
     # accesskey on the watch checkbox.  We also don't want to
     # give the edit tab an accesskey, because that's fairly
     # superfluous and conflicts with an accesskey (Ctrl-E) often
     # used for editing in Safari.
     if (in_array($action, array('edit', 'submit'))) {
         if (isset($content_navigation['views']['edit'])) {
             $content_navigation['views']['edit']['tooltiponly'] = true;
         }
         if (isset($content_navigation['actions']['watch'])) {
             $content_navigation['actions']['watch']['tooltiponly'] = true;
         }
         if (isset($content_navigation['actions']['unwatch'])) {
             $content_navigation['actions']['unwatch']['tooltiponly'] = true;
         }
     }
     return $content_navigation;
 }
Exemplo n.º 10
0
 /**
  * Stop watching a page
  * @return bool true on successful unwatch
  * @deprecated since 1.18
  */
 public function doUnwatch()
 {
     wfDeprecated(__METHOD__, '1.18');
     return WatchAction::doUnwatch($this->getTitle(), $this->getContext()->getUser());
 }
Exemplo n.º 11
0
 function doSubmit()
 {
     $user = $this->getUser();
     if ($user->pingLimiter('move')) {
         throw new ThrottledError();
     }
     $ot = $this->oldTitle;
     $nt = $this->newTitle;
     # don't allow moving to pages with # in
     if (!$nt || $nt->hasFragment()) {
         $this->showForm(array(array('badtitletext')));
         return;
     }
     # Show a warning if the target file exists on a shared repo
     if ($nt->getNamespace() == NS_FILE && !($this->moveOverShared && $user->isAllowed('reupload-shared')) && !RepoGroup::singleton()->getLocalRepo()->findFile($nt) && wfFindFile($nt)) {
         $this->showForm(array(array('file-exists-sharedrepo')));
         return;
     }
     # Delete to make way if requested
     if ($this->deleteAndMove) {
         $permErrors = $nt->getUserPermissionsErrors('delete', $user);
         if (count($permErrors)) {
             # Only show the first error
             $this->showForm($permErrors);
             return;
         }
         $reason = $this->msg('delete_and_move_reason', $ot)->inContentLanguage()->text();
         // Delete an associated image if there is
         if ($nt->getNamespace() == NS_FILE) {
             $file = wfLocalFile($nt);
             $file->load(File::READ_LATEST);
             if ($file->exists()) {
                 $file->delete($reason, false, $user);
             }
         }
         $error = '';
         // passed by ref
         $page = WikiPage::factory($nt);
         $deleteStatus = $page->doDeleteArticleReal($reason, false, 0, true, $error, $user);
         if (!$deleteStatus->isGood()) {
             $this->showForm($deleteStatus->getErrorsArray());
             return;
         }
     }
     $handler = ContentHandler::getForTitle($ot);
     if (!$handler->supportsRedirects()) {
         $createRedirect = false;
     } elseif ($user->isAllowed('suppressredirect')) {
         $createRedirect = $this->leaveRedirect;
     } else {
         $createRedirect = true;
     }
     # Do the actual move.
     $mp = new MovePage($ot, $nt);
     $valid = $mp->isValidMove();
     if (!$valid->isOK()) {
         $this->showForm($valid->getErrorsArray());
         return;
     }
     $permStatus = $mp->checkPermissions($user, $this->reason);
     if (!$permStatus->isOK()) {
         $this->showForm($permStatus->getErrorsArray());
         return;
     }
     $status = $mp->move($user, $this->reason, $createRedirect);
     if (!$status->isOK()) {
         $this->showForm($status->getErrorsArray());
         return;
     }
     if ($this->getConfig()->get('FixDoubleRedirects') && $this->fixRedirects) {
         DoubleRedirectJob::fixRedirects('move', $ot, $nt);
     }
     $out = $this->getOutput();
     $out->setPageTitle($this->msg('pagemovedsub'));
     $oldLink = Linker::link($ot, null, array('id' => 'movepage-oldlink'), array('redirect' => 'no'));
     $newLink = Linker::linkKnown($nt, null, array('id' => 'movepage-newlink'));
     $oldText = $ot->getPrefixedText();
     $newText = $nt->getPrefixedText();
     if ($ot->exists()) {
         // NOTE: we assume that if the old title exists, it's because it was re-created as
         // a redirect to the new title. This is not safe, but what we did before was
         // even worse: we just determined whether a redirect should have been created,
         // and reported that it was created if it should have, without any checks.
         // Also note that isRedirect() is unreliable because of bug 37209.
         $msgName = 'movepage-moved-redirect';
     } else {
         $msgName = 'movepage-moved-noredirect';
     }
     $out->addHTML($this->msg('movepage-moved')->rawParams($oldLink, $newLink)->params($oldText, $newText)->parseAsBlock());
     $out->addWikiMsg($msgName);
     Hooks::run('SpecialMovepageAfterMove', array(&$this, &$ot, &$nt));
     # Now we move extra pages we've been asked to move: subpages and talk
     # pages.  First, if the old page or the new page is a talk page, we
     # can't move any talk pages: cancel that.
     if ($ot->isTalkPage() || $nt->isTalkPage()) {
         $this->moveTalk = false;
     }
     if (count($ot->getUserPermissionsErrors('move-subpages', $user))) {
         $this->moveSubpages = false;
     }
     # Next make a list of id's.  This might be marginally less efficient
     # than a more direct method, but this is not a highly performance-cri-
     # tical code path and readable code is more important here.
     #
     # Note: this query works nicely on MySQL 5, but the optimizer in MySQL
     # 4 might get confused.  If so, consider rewriting as a UNION.
     #
     # If the target namespace doesn't allow subpages, moving with subpages
     # would mean that you couldn't move them back in one operation, which
     # is bad.
     # @todo FIXME: A specific error message should be given in this case.
     // @todo FIXME: Use Title::moveSubpages() here
     $dbr = wfGetDB(DB_MASTER);
     if ($this->moveSubpages && (MWNamespace::hasSubpages($nt->getNamespace()) || $this->moveTalk && MWNamespace::hasSubpages($nt->getTalkPage()->getNamespace()))) {
         $conds = array('page_title' . $dbr->buildLike($ot->getDBkey() . '/', $dbr->anyString()) . ' OR page_title = ' . $dbr->addQuotes($ot->getDBkey()));
         $conds['page_namespace'] = array();
         if (MWNamespace::hasSubpages($nt->getNamespace())) {
             $conds['page_namespace'][] = $ot->getNamespace();
         }
         if ($this->moveTalk && MWNamespace::hasSubpages($nt->getTalkPage()->getNamespace())) {
             $conds['page_namespace'][] = $ot->getTalkPage()->getNamespace();
         }
     } elseif ($this->moveTalk) {
         $conds = array('page_namespace' => $ot->getTalkPage()->getNamespace(), 'page_title' => $ot->getDBkey());
     } else {
         # Skip the query
         $conds = null;
     }
     $extraPages = array();
     if (!is_null($conds)) {
         $extraPages = TitleArray::newFromResult($dbr->select('page', array('page_id', 'page_namespace', 'page_title'), $conds, __METHOD__));
     }
     $extraOutput = array();
     $count = 1;
     foreach ($extraPages as $oldSubpage) {
         if ($ot->equals($oldSubpage) || $nt->equals($oldSubpage)) {
             # Already did this one.
             continue;
         }
         $newPageName = preg_replace('#^' . preg_quote($ot->getDBkey(), '#') . '#', StringUtils::escapeRegexReplacement($nt->getDBkey()), $oldSubpage->getDBkey());
         if ($oldSubpage->isSubpage() && ($ot->isTalkPage() xor $nt->isTalkPage())) {
             // Moving a subpage from a subject namespace to a talk namespace or vice-versa
             $newNs = $nt->getNamespace();
         } elseif ($oldSubpage->isTalkPage()) {
             $newNs = $nt->getTalkPage()->getNamespace();
         } else {
             $newNs = $nt->getSubjectPage()->getNamespace();
         }
         # Bug 14385: we need makeTitleSafe because the new page names may
         # be longer than 255 characters.
         $newSubpage = Title::makeTitleSafe($newNs, $newPageName);
         if (!$newSubpage) {
             $oldLink = Linker::linkKnown($oldSubpage);
             $extraOutput[] = $this->msg('movepage-page-unmoved')->rawParams($oldLink)->params(Title::makeName($newNs, $newPageName))->escaped();
             continue;
         }
         # This was copy-pasted from Renameuser, bleh.
         if ($newSubpage->exists() && !$oldSubpage->isValidMoveTarget($newSubpage)) {
             $link = Linker::linkKnown($newSubpage);
             $extraOutput[] = $this->msg('movepage-page-exists')->rawParams($link)->escaped();
         } else {
             $success = $oldSubpage->moveTo($newSubpage, true, $this->reason, $createRedirect);
             if ($success === true) {
                 if ($this->fixRedirects) {
                     DoubleRedirectJob::fixRedirects('move', $oldSubpage, $newSubpage);
                 }
                 $oldLink = Linker::link($oldSubpage, null, array(), array('redirect' => 'no'));
                 $newLink = Linker::linkKnown($newSubpage);
                 $extraOutput[] = $this->msg('movepage-page-moved')->rawParams($oldLink, $newLink)->escaped();
                 ++$count;
                 $maximumMovedPages = $this->getConfig()->get('MaximumMovedPages');
                 if ($count >= $maximumMovedPages) {
                     $extraOutput[] = $this->msg('movepage-max-pages')->numParams($maximumMovedPages)->escaped();
                     break;
                 }
             } else {
                 $oldLink = Linker::linkKnown($oldSubpage);
                 $newLink = Linker::link($newSubpage);
                 $extraOutput[] = $this->msg('movepage-page-unmoved')->rawParams($oldLink, $newLink)->escaped();
             }
         }
     }
     if ($extraOutput !== array()) {
         $out->addHTML("<ul>\n<li>" . implode("</li>\n<li>", $extraOutput) . "</li>\n</ul>");
     }
     # Deal with watches (we don't watch subpages)
     WatchAction::doWatchOrUnwatch($this->watch, $ot, $user);
     WatchAction::doWatchOrUnwatch($this->watch, $nt, $user);
 }
Exemplo n.º 12
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();
     }
 }
Exemplo n.º 13
0
 function watchThisPage()
 {
     global $wgOut, $wgUser;
     ++$this->mWatchLinkNum;
     // Cache
     $title = $this->getSkin()->getTitle();
     if ($wgOut->isArticleRelated()) {
         if ($wgUser->isWatched($title)) {
             $text = wfMessage('unwatchthispage')->text();
             $query = array('action' => 'unwatch', 'token' => UnwatchAction::getUnwatchToken($title, $wgUser));
             $id = 'mw-unwatch-link' . $this->mWatchLinkNum;
         } else {
             $text = wfMessage('watchthispage')->text();
             $query = array('action' => 'watch', 'token' => WatchAction::getWatchToken($title, $wgUser));
             $id = 'mw-watch-link' . $this->mWatchLinkNum;
         }
         $s = Linker::linkKnown($title, $text, array('id' => $id), $query);
     } else {
         $s = wfMessage('notanarticle')->text();
     }
     return $s;
 }
Exemplo n.º 14
0
 /**
  * Stop watching a page
  * @return bool true on successful unwatch
  * @deprecated since 1.18
  */
 public function doUnwatch()
 {
     global $wgUser;
     wfDeprecated(__METHOD__, '1.18');
     return WatchAction::doUnwatch($this->getTitle(), $wgUser);
 }
Exemplo n.º 15
0
 /**
  * @param $thread Thread
  */
 function topLevelThreadCommands($thread)
 {
     $commands = array();
     $commands['history'] = array('label' => wfMessage('history_short')->parse(), 'href' => self::permalinkUrl($thread, 'thread_history'), 'enabled' => true);
     if ($this->user->isAllowed('move')) {
         $move_href = SpecialPage::getTitleFor('MoveThread', $thread->title()->getPrefixedText())->getLocalURL();
         $commands['move'] = array('label' => wfMessage('lqt-movethread')->parse(), 'href' => $move_href, 'enabled' => true);
     }
     if ($this->user->isAllowed('protect')) {
         $protect_href = $thread->title()->getLocalURL('action=protect');
         // Check if it's already protected
         if (!$thread->title()->isProtected()) {
             $label = wfMessage('protect')->parse();
         } else {
             $label = wfMessage('unprotect')->parse();
         }
         $commands['protect'] = array('label' => $label, 'href' => $protect_href, 'enabled' => true);
     }
     if (!$this->user->isAnon() && !$thread->title()->userIsWatching()) {
         $commands['watch'] = array('label' => wfMessage('watch')->parse(), 'href' => self::permalinkUrlWithQuery($thread, array('action' => 'watch', 'token' => WatchAction::getWatchToken($thread->title(), $this->user, 'watch'))), 'enabled' => true);
     } elseif (!$this->user->isAnon()) {
         $commands['unwatch'] = array('label' => wfMessage('unwatch')->parse(), 'href' => self::permalinkUrlWithQuery($thread, array('action' => 'unwatch', 'token' => WatchAction::getWatchToken($thread->title(), $this->user, 'unwatch'))), 'enabled' => true);
     }
     if (LqtDispatch::isLqtPage($thread->getTitle())) {
         $summarizeUrl = self::permalinkUrl($thread, 'summarize', $thread->id());
         $commands['summarize'] = array('label' => wfMessage('lqt_summarize_link')->parse(), 'href' => $summarizeUrl, 'enabled' => true);
     }
     Hooks::run('LiquidThreadsTopLevelCommands', array($thread, &$commands));
     return $commands;
 }
Exemplo n.º 16
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;
         }
     }
     $this->mCascade = $wgRequest->getBool('mwProtect-cascade');
     $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, $reasonstr))) {
         if ($errorMsg == '') {
             $errorMsg = array('hookaborted');
         }
     }
     if ($errorMsg != '') {
         $this->show($errorMsg);
         return false;
     }
     WatchAction::doWatchOrUnwatch($wgRequest->getCheck('mwProtectWatch'), $this->mTitle, $wgUser);
     return true;
 }
Exemplo n.º 17
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;
 }
Exemplo n.º 18
0
 /**
  * Register the change of watch status
  */
 protected function updateWatchlist()
 {
     global $wgUser;
     if ($wgUser->isLoggedIn() && $this->watchthis != $wgUser->isWatched($this->mTitle, WatchedItem::IGNORE_USER_RIGHTS)) {
         $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) {
             WatchAction::doWatchOrUnwatch($watch, $title, $wgUser);
         });
     }
 }
Exemplo n.º 19
0
 /**
  * Register the change of watch status
  */
 protected function updateWatchlist()
 {
     global $wgUser;
     if (!$wgUser->isLoggedIn()) {
         return;
     }
     $user = $wgUser;
     $title = $this->mTitle;
     $watch = $this->watchthis;
     // Do this in its own transaction to reduce contention...
     DeferredUpdates::addCallableUpdate(function () use($user, $title, $watch) {
         if ($watch == $user->isWatched($title, WatchedItem::IGNORE_USER_RIGHTS)) {
             return;
             // nothing to change
         }
         WatchAction::doWatchOrUnwatch($watch, $title, $user);
     });
 }
Exemplo n.º 20
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;
 }
Exemplo n.º 21
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;
 }
Exemplo n.º 22
0
 /**
  * Set a watch (or unwatch) based the based on a watchlist parameter.
  * @param string $watch Valid values: 'watch', 'unwatch', 'preferences', 'nochange'
  * @param Title $titleObj The article's title to change
  * @param string $userOption 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;
     }
     WatchAction::doWatchOrUnwatch($value, $titleObj, $this->getUser());
 }
Exemplo n.º 23
0
 /**
  * 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());
             WatchAction::doWatchOrUnwatch($wgRequest->getCheck('wpWatch'), $this->title, $wgUser);
         }
         return;
     }
     $this->showForm();
     $this->showLogEntries();
 }
Exemplo n.º 24
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);
         });
     }
 }
Exemplo n.º 25
0
 /**
  * UI entry point for page deletion
  */
 public function delete()
 {
     # This code desperately needs to be totally rewritten
     $title = $this->getTitle();
     $context = $this->getContext();
     $user = $context->getUser();
     # Check permissions
     $permissionErrors = $title->getUserPermissionsErrors('delete', $user);
     if (count($permissionErrors)) {
         throw new PermissionsError('delete', $permissionErrors);
     }
     # Read-only check...
     if (wfReadOnly()) {
         throw new ReadOnlyError();
     }
     # Better double-check that it hasn't been deleted yet!
     $this->mPage->loadPageData('fromdbmaster');
     if (!$this->mPage->exists()) {
         $deleteLogPage = new LogPage('delete');
         $outputPage = $context->getOutput();
         $outputPage->setPageTitle($context->msg('cannotdelete-title', $title->getPrefixedText()));
         $outputPage->wrapWikiMsg("<div class=\"error mw-error-cannotdelete\">\n\$1\n</div>", array('cannotdelete', wfEscapeWikiText($title->getPrefixedText())));
         $outputPage->addHTML(Xml::element('h2', null, $deleteLogPage->getName()->text()));
         LogEventsList::showLogExtract($outputPage, 'delete', $title);
         return;
     }
     $request = $context->getRequest();
     $deleteReasonList = $request->getText('wpDeleteReasonList', 'other');
     $deleteReason = $request->getText('wpReason');
     if ($deleteReasonList == 'other') {
         $reason = $deleteReason;
     } elseif ($deleteReason != '') {
         // Entry from drop down menu + additional comment
         $colonseparator = wfMessage('colon-separator')->inContentLanguage()->text();
         $reason = $deleteReasonList . $colonseparator . $deleteReason;
     } else {
         $reason = $deleteReasonList;
     }
     if ($request->wasPosted() && $user->matchEditToken($request->getVal('wpEditToken'), array('delete', $this->getTitle()->getPrefixedText()))) {
         # Flag to hide all contents of the archived revisions
         $suppress = $request->getVal('wpSuppress') && $user->isAllowed('suppressrevision');
         $this->doDelete($reason, $suppress);
         WatchAction::doWatchOrUnwatch($request->getCheck('wpWatch'), $title, $user);
         return;
     }
     // Generate deletion reason
     $hasHistory = false;
     if (!$reason) {
         try {
             $reason = $this->generateReason($hasHistory);
         } catch (Exception $e) {
             # if a page is horribly broken, we still want to be able to
             # delete it. So be lenient about errors here.
             wfDebug("Error while building auto delete summary: {$e}");
             $reason = '';
         }
     }
     // If the page has a history, insert a warning
     if ($hasHistory) {
         $title = $this->getTitle();
         // The following can use the real revision count as this is only being shown for users
         // that can delete this page.
         // This, as a side-effect, also makes sure that the following query isn't being run for
         // pages with a larger history, unless the user has the 'bigdelete' right
         // (and is about to delete this page).
         $dbr = wfGetDB(DB_SLAVE);
         $revisions = $edits = (int) $dbr->selectField('revision', 'COUNT(rev_page)', array('rev_page' => $title->getArticleID()), __METHOD__);
         // @todo FIXME: i18n issue/patchwork message
         $context->getOutput()->addHTML('<strong class="mw-delete-warning-revisions">' . $context->msg('historywarning')->numParams($revisions)->parse() . $context->msg('word-separator')->escaped() . Linker::linkKnown($title, $context->msg('history')->escaped(), array(), array('action' => 'history')) . '</strong>');
         if ($title->isBigDeletion()) {
             global $wgDeleteRevisionsLimit;
             $context->getOutput()->wrapWikiMsg("<div class='error'>\n\$1\n</div>\n", array('delete-warning-toobig', $context->getLanguage()->formatNum($wgDeleteRevisionsLimit)));
         }
     }
     $this->confirmDelete($reason);
 }
Exemplo n.º 26
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);
     }
 }
Exemplo n.º 27
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;
 }
Exemplo n.º 28
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;
 }
 /**
  * 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;
 }
Exemplo n.º 30
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;
 }