Example #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) {
         $this->dieUsageMsg(array('invalidtitle', $params['title']));
     }
     $article = new Article($title);
     $res = array('title' => $title->getPrefixedText());
     if ($params['unwatch']) {
         $res['unwatched'] = '';
         $success = $article->doUnwatch();
     } else {
         $res['watched'] = '';
         $success = $article->doWatch();
     }
     if (!$success) {
         $this->dieUsageMsg(array('hookaborted'));
     }
     $this->getResult()->addValue(null, $this->getModuleName(), $res);
 }
Example #2
0
/**
 * Called for AJAX watch/unwatch requests.
 * @param $pagename Prefixed title string for page to watch/unwatch
 * @param $watch String 'w' to watch, 'u' to unwatch
 * @return String '<w#>' or '<u#>' on successful watch or unwatch,
 *   respectively, followed by an HTML message to display in the alert box; or
 *   '<err#>' on error
 */
function wfAjaxWatch($pagename = "", $watch = "")
{
    if (wfReadOnly()) {
        // redirect to action=(un)watch, which will display the database lock
        // message
        return '<err#>';
    }
    if ('w' !== $watch && 'u' !== $watch) {
        return '<err#>';
    }
    $watch = 'w' === $watch;
    $title = Title::newFromDBkey($pagename);
    if (!$title) {
        // Invalid title
        return '<err#>';
    }
    $article = new Article($title);
    $watching = $title->userIsWatching();
    if ($watch) {
        if (!$watching) {
            $dbw = wfGetDB(DB_MASTER);
            $dbw->begin();
            $ok = $article->doWatch();
            $dbw->commit();
        }
    } else {
        if ($watching) {
            $dbw = wfGetDB(DB_MASTER);
            $dbw->begin();
            $ok = $article->doUnwatch();
            $dbw->commit();
        }
    }
    // Something stopped the change
    if (isset($ok) && !$ok) {
        return '<err#>';
    }
    if ($watch) {
        return '<w#>' . wfMsgExt('addedwatchtext', array('parse'), $title->getPrefixedText());
    } else {
        return '<u#>' . wfMsgExt('removedwatchtext', array('parse'), $title->getPrefixedText());
    }
}
Example #3
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);
         $error = '';
         $dbw = wfGetDB(DB_MASTER);
         try {
             if (wfRunHooks('ArticleDelete', array(&$article, &$wgUser, &$reason, &$error))) {
                 // delete the associated article first
                 if ($article->doDeleteArticle($reason, $suppress, $id, false)) {
                     global $wgRequest;
                     if ($wgRequest->getCheck('wpWatch') && $wgUser->isLoggedIn()) {
                         $article->doWatch();
                     } elseif ($title->userIsWatching()) {
                         $article->doUnwatch();
                     }
                     $status = $file->delete($reason, $suppress);
                     if ($status->ok) {
                         $dbw->commit();
                         wfRunHooks('ArticleDeleteComplete', array(&$article, &$wgUser, $reason, $id));
                     } 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;
 }
Example #4
0
 public function execute()
 {
     global $wgUser, $wgRestrictionTypes, $wgRestrictionLevels;
     $params = $this->extractRequestParams();
     $titleObj = NULL;
     if (!isset($params['title'])) {
         $this->dieUsageMsg(array('missingparam', 'title'));
     }
     if (!isset($params['token'])) {
         $this->dieUsageMsg(array('missingparam', 'token'));
     }
     if (empty($params['protections'])) {
         $this->dieUsageMsg(array('missingparam', 'protections'));
     }
     if (!$wgUser->matchEditToken($params['token'])) {
         $this->dieUsageMsg(array('sessionfailure'));
     }
     $titleObj = Title::newFromText($params['title']);
     if (!$titleObj) {
         $this->dieUsageMsg(array('invalidtitle', $params['title']));
     }
     $errors = $titleObj->getUserPermissionsErrors('protect', $wgUser);
     if ($errors) {
         // We don't care about multiple errors, just report one of them
         $this->dieUsageMsg(reset($errors));
     }
     $expiry = (array) $params['expiry'];
     if (count($expiry) != count($params['protections'])) {
         if (count($expiry) == 1) {
             $expiry = array_fill(0, count($params['protections']), $expiry[0]);
         } else {
             $this->dieUsageMsg(array('toofewexpiries', count($expiry), count($params['protections'])));
         }
     }
     $protections = array();
     $expiryarray = array();
     $resultProtections = array();
     foreach ($params['protections'] as $i => $prot) {
         $p = explode('=', $prot);
         $protections[$p[0]] = $p[1] == 'all' ? '' : $p[1];
         if ($titleObj->exists() && $p[0] == 'create') {
             $this->dieUsageMsg(array('create-titleexists'));
         }
         if (!$titleObj->exists() && $p[0] != 'create') {
             $this->dieUsageMsg(array('missingtitles-createonly'));
         }
         if (!in_array($p[0], $wgRestrictionTypes) && $p[0] != 'create') {
             $this->dieUsageMsg(array('protect-invalidaction', $p[0]));
         }
         if (!in_array($p[1], $wgRestrictionLevels) && $p[1] != 'all') {
             $this->dieUsageMsg(array('protect-invalidlevel', $p[1]));
         }
         if (in_array($expiry[$i], array('infinite', 'indefinite', 'never'))) {
             $expiryarray[$p[0]] = Block::infinity();
         } else {
             $exp = strtotime($expiry[$i]);
             if ($exp < 0 || $exp == false) {
                 $this->dieUsageMsg(array('invalidexpiry', $expiry[$i]));
             }
             $exp = wfTimestamp(TS_MW, $exp);
             if ($exp < wfTimestampNow()) {
                 $this->dieUsageMsg(array('pastexpiry', $expiry[$i]));
             }
             $expiryarray[$p[0]] = $exp;
         }
         $resultProtections[] = array($p[0] => $protections[$p[0]], 'expiry' => $expiryarray[$p[0]] == Block::infinity() ? 'infinite' : wfTimestamp(TS_ISO_8601, $expiryarray[$p[0]]));
     }
     $cascade = $params['cascade'];
     $articleObj = new Article($titleObj);
     if ($params['watch']) {
         $articleObj->doWatch();
     }
     if ($titleObj->exists()) {
         $ok = $articleObj->updateRestrictions($protections, $params['reason'], $cascade, $expiryarray);
     } else {
         $ok = $titleObj->updateTitleProtection($protections['create'], $params['reason'], $expiryarray['create']);
     }
     if (!$ok) {
         // This is very weird. Maybe the article was deleted or the user was blocked/desysopped in the meantime?
         // Just throw an unknown error in this case, as it's very likely to be a race condition
         $this->dieUsageMsg(array());
     }
     $res = array('title' => $titleObj->getPrefixedText(), 'reason' => $params['reason']);
     if ($cascade) {
         $res['cascade'] = '';
     }
     $res['protections'] = $resultProtections;
     $this->getResult()->setIndexedTagName($res['protections'], 'protection');
     $this->getResult()->addValue(null, $this->getModuleName(), $res);
 }
Example #5
0
 public static function doDelete(&$title, &$file, &$oldimage, $reason, $suppress)
 {
     $article = null;
     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 .= ": {$reason}";
             }
             $log->addEntry('delete', $title, $logComment);
         }
     } else {
         $status = $file->delete($reason, $suppress);
         if ($status->ok) {
             $id = $title->getArticleID(GAID_FOR_UPDATE);
             // Need to delete the associated article
             $article = new Article($title);
             if (wfRunHooks('ArticleDelete', array(&$article, &$wgUser, &$reason))) {
                 if ($article->doDeleteArticle($reason, $suppress, $id)) {
                     global $wgRequest;
                     if ($wgRequest->getCheck('wpWatch')) {
                         $article->doWatch();
                     } elseif ($title->userIsWatching()) {
                         $article->doUnwatch();
                     }
                     wfRunHooks('ArticleDeleteComplete', array(&$article, &$wgUser, $reason, $id));
                 }
             }
         }
     }
     if ($status->isGood()) {
         wfRunHooks('FileDeleteComplete', array(&$file, &$oldimage, &$article, &$wgUser, &$reason));
     }
     return $status;
 }
	/**
	 * 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;
	}
Example #7
0
 /**
  * This is the meaty bit -- restores archived revisions of the given page
  * to the cur/old tables. If the page currently exists, all revisions will
  * be stuffed into old, otherwise the most recent will go into cur.
  *
  * @param array $timestamps Pass an empty array to restore all revisions, otherwise list the ones to undelete.
  * @param string $comment
  * @param array $fileVersions
  *
  * @return int number of revisions restored
  */
 private function undeleteRevisions($timestamps)
 {
     global $wgParser, $wgDBtype;
     $fname = __CLASS__ . '::' . __FUNCTION__;
     $restoreAll = empty($timestamps);
     $dbw =& wfGetDB(DB_MASTER);
     extract($dbw->tableNames('page', 'archive'));
     # Does this page already exist? We'll have to update it...
     $article = new Article($this->title);
     $options = $wgDBtype == 'postgres' ? '' : 'FOR UPDATE';
     $page = $dbw->selectRow('page', array('page_id', 'page_latest'), array('page_namespace' => $this->title->getNamespace(), 'page_title' => $this->title->getDBkey()), $fname, $options);
     if ($page) {
         # Page already exists. Import the history, and if necessary
         # we'll update the latest revision field in the record.
         $newid = 0;
         $pageId = $page->page_id;
         $previousRevId = $page->page_latest;
     } else {
         # Have to create a new article...
         $newid = $article->insertOn($dbw);
         $pageId = $newid;
         $previousRevId = 0;
     }
     if ($restoreAll) {
         $oldones = '1 = 1';
         # All revisions...
     } else {
         $oldts = implode(',', array_map(array(&$dbw, 'addQuotes'), array_map(array(&$dbw, 'timestamp'), $timestamps)));
         $oldones = "ar_timestamp IN ( {$oldts} )";
     }
     /**
      * Restore each revision...
      */
     $result = $dbw->select('archive', array('ar_rev_id', 'ar_text', 'ar_comment', 'ar_user', 'ar_user_text', 'ar_timestamp', 'ar_minor_edit', 'ar_flags', 'ar_text_id'), array('ar_namespace' => $this->title->getNamespace(), 'ar_title' => $this->title->getDBkey(), $oldones), $fname, array('ORDER BY' => 'ar_timestamp'));
     if ($dbw->numRows($result) < count($timestamps)) {
         wfDebug("{$fname}: couldn't find all requested rows\n");
         return false;
     }
     $revision = null;
     $newRevId = $previousRevId;
     $restored = 0;
     while ($row = $dbw->fetchObject($result)) {
         if ($row->ar_text_id) {
             // Revision was deleted in 1.5+; text is in
             // the regular text table, use the reference.
             // Specify null here so the so the text is
             // dereferenced for page length info if needed.
             $revText = null;
         } else {
             // Revision was deleted in 1.4 or earlier.
             // Text is squashed into the archive row, and
             // a new text table entry will be created for it.
             $revText = Revision::getRevisionText($row, 'ar_');
         }
         $revision = new Revision(array('page' => $pageId, 'id' => $row->ar_rev_id, 'text' => $revText, 'comment' => $row->ar_comment, 'user' => $row->ar_user, 'user_text' => $row->ar_user_text, 'timestamp' => $row->ar_timestamp, 'minor_edit' => $row->ar_minor_edit, 'text_id' => $row->ar_text_id));
         $newRevId = $revision->insertOn($dbw);
         $restored++;
     }
     if ($revision) {
         # FIXME: Update latest if newer as well...
         if ($newid) {
             # FIXME: update article count if changed...
             $article->updateRevisionOn($dbw, $revision, $previousRevId);
             # Finally, clean up the link tables
             $options = new ParserOptions();
             $parserOutput = $wgParser->parse($revision->getText(), $this->title, $options, true, true, $newRevId);
             $u = new LinksUpdate($this->title, $parserOutput);
             $u->doUpdate();
             #TODO: SearchUpdate, etc.
         }
         // WERELATE: watch article
         global $wgUser;
         $watchthis = false;
         if ($newid) {
             Article::onArticleCreate($this->title);
             $watchthis = $wgUser->getOption('watchcreations') || $wgUser->getOption('watchdefault');
         } else {
             Article::onArticleEdit($this->title);
             $watchthis = $wgUser->getOption('watchdefault');
         }
         if ($watchthis && !$article->getTitle()->userIsWatching()) {
             $article->doWatch();
         }
     } else {
         # Something went terribly wrong!
     }
     # Now that it's safely stored, take it out of the archive
     $dbw->delete('archive', array('ar_namespace' => $this->title->getNamespace(), 'ar_title' => $this->title->getDBkey(), $oldones), $fname);
     return $restored;
 }
Example #8
0
/**
 * Called for AJAX watch/unwatch requests.
 * @param $pageID Integer ID of the page to be watched/unwatched
 * @param $watch String 'w' to watch, 'u' to unwatch
 * @return String '<w#>' or '<u#>' on successful watch or unwatch, respectively, or '<err#>' on error (invalid XML in case we want to add HTML sometime)
 */
function wfAjaxWatch($pageID = "", $watch = "")
{
    if (wfReadOnly()) {
        return '<err#>';
    }
    // redirect to action=(un)watch, which will display the database lock message
    if ('w' !== $watch && 'u' !== $watch || !is_numeric($pageID)) {
        return '<err#>';
    }
    $watch = 'w' === $watch;
    $pageID = intval($pageID);
    $title = Title::newFromID($pageID);
    if (!$title) {
        return '<err#>';
    }
    $article = new Article($title);
    $watching = $title->userIsWatching();
    if ($watch) {
        if (!$watching) {
            $dbw =& wfGetDB(DB_MASTER);
            $dbw->begin();
            $article->doWatch();
            $dbw->commit();
        }
    } else {
        if ($watching) {
            $dbw =& wfGetDB(DB_MASTER);
            $dbw->begin();
            $article->doUnwatch();
            $dbw->commit();
        }
    }
    return $watch ? '<w#>' : '<u#>';
}
Example #9
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;
     }
     $articleObj = new Article($titleObj);
     if ($value) {
         $articleObj->doWatch();
     } else {
         $articleObj->doUnwatch();
     }
 }