protected function logTagAdded($tags, $revId, $user, $reason) { // log it $logEntry = new ManualLogEntry('tag', 'update'); $logEntry->setPerformer($user); $logEntry->setComment($reason); // find the appropriate target page if ($revId) { $rev = Revision::newFromId($revId); if ($rev) { $logEntry->setTarget($rev->getTitle()); } } if (!$logEntry->getTarget()) { // target is required, so we have to set something $logEntry->setTarget(SpecialPage::getTitleFor('Tags')); } $logParams = array('4::revid' => $revId, '6:list:tagsAdded' => $tags, '7:number:tagsAddedCount' => count($tags)); $logEntry->setParameters($logParams); $logEntry->setRelations(array('Tag' => $tags)); $dbw = wfGetDB(DB_MASTER); $logId = $logEntry->insert($dbw); // Only send this to UDP, not RC, similar to patrol events $logEntry->publish($logId, 'udp'); //$logEntry->publish( $logId ); }
public function execute() { $out = $this->mSpecial->getOutput(); $dbw = wfGetDB(DB_MASTER); $row = $dbw->selectRow('moderation', array('mod_user AS user', 'mod_user_text AS user_text'), array('mod_id' => $this->id), __METHOD__); if (!$row) { throw new ModerationError('moderation-edit-not-found'); } $dbw = wfGetDB(DB_MASTER); if ($this->actionName == 'block') { $dbw->replace('moderation_block', array('mb_address'), array('mb_address' => $row->user_text, 'mb_user' => $row->user, 'mb_by' => $this->moderator->getId(), 'mb_by_text' => $this->moderator->getName(), 'mb_timestamp' => $dbw->timestamp(wfTimestampNow())), __METHOD__); $logEntry = new ManualLogEntry('moderation', 'block'); } else { $dbw->delete('moderation_block', array('mb_address' => $row->user_text), __METHOD__); $logEntry = new ManualLogEntry('moderation', 'unblock'); } $nrows = $dbw->affectedRows(); if ($nrows > 0) { $logEntry->setPerformer($this->moderator); $logEntry->setTarget(Title::makeTitle(NS_USER, $row->user_text)); $logid = $logEntry->insert(); $logEntry->publish($logid); } $out->addWikiMsg('moderation-' . ($this->actionName == 'unblock' ? 'un' : '') . 'block-' . ($nrows ? 'ok' : 'fail'), $row->user_text); }
/** * Record a log event for a change being patrolled * * @param mixed $rc Change identifier or RecentChange object * @param bool $auto Was this patrol event automatic? * @param User $user User performing the action or null to use $wgUser * * @return bool */ public static function record($rc, $auto = false, User $user = null) { global $wgLogAutopatrol; // do not log autopatrolled edits if setting disables it if ($auto && !$wgLogAutopatrol) { return false; } if (!$rc instanceof RecentChange) { $rc = RecentChange::newFromId($rc); if (!is_object($rc)) { return false; } } if (!$user) { global $wgUser; $user = $wgUser; } $entry = new ManualLogEntry('patrol', 'patrol'); $entry->setTarget($rc->getTitle()); $entry->setParameters(self::buildParams($rc, $auto)); $entry->setPerformer($user); $logid = $entry->insert(); if (!$auto) { $entry->publish($logid, 'udp'); } return true; }
public function executeRejectAll() { $out = $this->mSpecial->getOutput(); $userpage = $this->mSpecial->getUserpageByModId($this->id); if (!$userpage) { throw new ModerationError('moderation-edit-not-found'); } $dbw = wfGetDB(DB_MASTER); # Need latest data without lag $res = $dbw->select('moderation', array('mod_id AS id'), array('mod_user_text' => $userpage->getText(), 'mod_rejected' => 0, 'mod_merged_revid' => 0), __METHOD__, array('USE INDEX' => 'moderation_rejectall')); if (!$res || $res->numRows() == 0) { throw new ModerationError('moderation-nothing-to-rejectall'); } $ids = array(); foreach ($res as $row) { $ids[] = $row->id; } $dbw->update('moderation', array('mod_rejected' => 1, 'mod_rejected_by_user' => $this->moderator->getId(), 'mod_rejected_by_user_text' => $this->moderator->getName(), 'mod_rejected_batch' => 1, 'mod_preloadable' => 0), array('mod_id' => $ids), __METHOD__); $nrows = $dbw->affectedRows(); if ($nrows) { $logEntry = new ManualLogEntry('moderation', 'rejectall'); $logEntry->setPerformer($this->moderator); $logEntry->setTarget($userpage); $logEntry->setParameters(array('4::count' => $nrows)); $logid = $logEntry->insert(); $logEntry->publish($logid); } $out->addWikiMsg('moderation-rejected-ok', $nrows); }
public function onSubmit(array $formData) { global $IP, $wgCreateWikiSQLfiles; $DBname = $formData['dbname']; $founderName = $formData['founder']; $siteName = $formData['sitename']; $language = $formData['language']; $private = $formData['private']; $reason = $formData['reason']; $dbw = wfGetDB(DB_MASTER); $farmerLogEntry = new ManualLogEntry('farmer', 'createwiki'); $farmerLogEntry->setPerformer($this->getUser()); $farmerLogEntry->setTarget($this->getTitle()); $farmerLogEntry->setComment($reason); $farmerLogEntry->setParameters(array('4::wiki' => $DBname)); $farmerLogID = $farmerLogEntry->insert(); $farmerLogEntry->publish($farmerLogID); $dbw->query('SET storage_engine=InnoDB;'); $dbw->query('CREATE DATABASE ' . $dbw->addIdentifierQuotes($DBname) . ';'); $dbw->selectDB($DBname); foreach ($wgCreateWikiSQLfiles as $sqlfile) { $dbw->sourceFile($sqlfile); } $this->writeToDBlist($DBname, $siteName, $language, $private); $this->createMainPage($language); $shcreateaccount = exec("/usr/bin/php " . "{$IP}/extensions/CentralAuth/maintenance/createLocalAccount.php " . wfEscapeShellArg($founderName) . " --wiki " . wfEscapeShellArg($DBname)); if (!strpos($shcreateaccount, 'created')) { wfDebugLog('CreateWiki', 'Failed to create local account for founder. - error: ' . $shcreateaccount); return wfMessage('createwiki-error-usernotcreated')->escaped(); } $shpromoteaccount = exec("/usr/bin/php " . "{$IP}/maintenance/createAndPromote.php " . wfEscapeShellArg($founderName) . " --bureaucrat --sysop --force --wiki " . wfEscapeShellArg($DBname)); $this->getOutput()->addHTML('<div class="successbox">' . wfMessage('createwiki-success')->escaped() . '</div>'); return true; }
public function execute($par) { // Shortcut by using $par if ($par) { $this->getOutput()->redirect($this->getTitle()->getLinkURL(array('user' => $par))); return; } $this->setHeaders(); $this->outputHeader(); // Parse options $opt = new \FormOptions(); $opt->add('user', ''); $opt->add('delete', ''); $opt->add('reason', ''); $opt->fetchValuesFromRequest($this->getRequest()); // Parse user $user = $opt->getValue('user'); $userObj = \User::newFromName($user); $userExists = $userObj && $userObj->getId() !== 0; // If current task is delete and user is not allowed $canDoAdmin = $this->getUser()->isAllowed('avataradmin'); if ($opt->getValue('delete')) { if (!$canDoAdmin) { throw new \PermissionsError('avataradmin'); } // Delete avatar if the user exists if ($userExists) { if (Avatars::deleteAvatar($userObj)) { global $wgAvatarLogInRC; $logEntry = new \ManualLogEntry('avatar', 'delete'); $logEntry->setPerformer($this->getUser()); $logEntry->setTarget($userObj->getUserPage()); $logEntry->setComment($opt->getValue('reason')); $logId = $logEntry->insert(); $logEntry->publish($logId, $wgAvatarLogInRC ? 'rcandudp' : 'udp'); } } } $this->getOutput()->addModules(array('mediawiki.userSuggest')); $this->showForm($user); if ($userExists) { $haveAvatar = Avatars::hasAvatar($userObj); if ($haveAvatar) { $html = \Xml::tags('img', array('src' => Avatars::getLinkFor($user, 'original') . '&nocache&ver=' . dechex(time()), 'height' => 400), ''); $html = \Xml::tags('p', array(), $html); $this->getOutput()->addHTML($html); // Add a delete button if ($canDoAdmin) { $this->showDeleteForm($user); } } else { $this->getOutput()->addWikiMsg('viewavatar-noavatar'); } } else { if ($user) { $this->getOutput()->addWikiMsg('viewavatar-nouser'); } } }
public function newLogEntry($action, $params) { $logEntry = new ManualLogEntry('phpunit', $action); $logEntry->setPerformer($this->user); $logEntry->setTarget($this->title); $logEntry->setComment('A very good reason'); $logEntry->setParameters($params); return $logEntry; }
/** * Log the promotion of a local unattached to a global * * @param string $oldName * @param string $wiki * @param string $newName * @param string $reason */ public function logPromotion($oldName, $wiki, $newName, $reason) { $logEntry = new ManualLogEntry('gblrename', 'promote'); $logEntry->setPerformer($this->performingUser); $logEntry->setTarget(Title::makeTitleSafe(NS_SPECIAL, 'CentralAuth/' . $newName)); $logEntry->setComment($reason); $logEntry->setParameters(array('4::olduser' => $oldName, '5::newuser' => $newName, '6::oldwiki' => $wiki)); $logEntry->setRelations(array('oldname' => $oldName)); $logid = $logEntry->insert(); $logEntry->publish($logid); }
private function processUpload() { $request = $this->getRequest(); $dataurl = $request->getVal('avatar'); if (!$dataurl || parse_url($dataurl, PHP_URL_SCHEME) !== 'data') { $this->displayMessage($this->msg('avatar-notuploaded')); return false; } $img = Thumbnail::open($dataurl); global $wgMaxAvatarResolution; switch ($img->type) { case IMAGETYPE_GIF: case IMAGETYPE_PNG: case IMAGETYPE_JPEG: break; default: $this->displayMessage($this->msg('avatar-invalid')); return false; } // Must be square if ($img->width !== $img->height) { $this->displayMessage($this->msg('avatar-notsquare')); return false; } // Check if image is too small if ($img->width < 32 || $img->height < 32) { $this->displayMessage($this->msg('avatar-toosmall')); return false; } // Check if image is too big if ($img->width > $wgMaxAvatarResolution || $img->height > $wgMaxAvatarResolution) { $this->displayMessage($this->msg('avatar-toolarge')); return false; } // Avatar directories global $wgUploadDirectory; $uploadDir = $wgUploadDirectory . '/avatars/' . $this->getUser()->getId() . '/'; @mkdir($uploadDir, 0777, true); // We do this to convert format to png $img->createThumbnail($wgMaxAvatarResolution, $uploadDir . 'original.png'); // We only create thumbnail with default resolution here. Others are generated on demand global $wgDefaultAvatarRes; $img->createThumbnail($wgDefaultAvatarRes, $uploadDir . $wgDefaultAvatarRes . '.png'); $img->cleanup(); $this->displayMessage($this->msg('avatar-saved')); $logEntry = new \ManualLogEntry('avatar', 'upload'); $logEntry->setPerformer($this->getUser()); $logEntry->setTarget($this->getUser()->getUserPage()); $logId = $logEntry->insert(); $logEntry->publish($logId, 'rcandudp'); return true; }
/** * @param CentralAuthUser[] $oldNames * @param string $newName * @param string $reason */ public function log(array $oldNames, $newName, $reason) { $logEntry = new ManualLogEntry('gblrename', 'merge'); $logEntry->setPerformer($this->performingUser); $logEntry->setTarget(Title::makeTitleSafe(NS_SPECIAL, 'CentralAuth/' . $newName)); $imploded = implode('|', array_map(function (CentralAuthUser $user) { return $user->getName(); }, $oldNames)); $logEntry->setComment($reason); $logEntry->setParameters(array('4::olduser' => $imploded, '5::newuser' => $newName)); $logid = $logEntry->insert(); $logEntry->publish($logid); }
/** * adds a log entry to the database. * * @param $type string: type of the log entry * @param $subtype string: subtype of the log entry * @param $user User: user that performs the logged operation * @param $ns int: number of the namespace for the entry's target's title * @param $title string: title of the entry's target * @param $comment string: comment of the log entry * @param $parameters Array: (optional) accompanying data that is attached * to the entry * * @return int id of the added log entry */ private function addLogEntry($type, $subtype, User $user, $ns, $title, $comment = null, $parameters = null) { $logEntry = new ManualLogEntry($type, $subtype); $logEntry->setPerformer($user); $logEntry->setTarget(Title::newFromText($title, $ns)); if ($comment !== null) { $logEntry->setComment($comment); } if ($parameters !== null) { $logEntry->setParameters($parameters); } return $logEntry->insert(); }
function run() { // Unfortunately the global is needed until bug is fixed: // https://phabricator.wikimedia.org/T51086 // Once MW >= 1.24 is supported, can use MovePage class. global $wgUser; // Initialization $title = $this->title; // Other stuff $user = $this->getUser(); $summary = $this->getSummary(); $target = $this->getTarget(); $base = $this->params['base-source']; $doer = User::newFromName($this->getPerformer()); PageTranslationHooks::$allowTargetEdit = true; PageTranslationHooks::$jobQueueRunning = true; $oldUser = $wgUser; $wgUser = $user; self::forceRedirects(false); // Don't check perms, don't leave a redirect $ok = $title->moveTo($target, false, $summary, false); if (!$ok) { $params = array('target' => $target->getPrefixedText(), 'error' => $ok); $entry = new ManualLogEntry('pagetranslation', 'movenok'); $entry->setPerformer($doer); $entry->setTarget($title); $entry->setParameters($params); $logid = $entry->insert(); $entry->publish($logid); } self::forceRedirects(true); PageTranslationHooks::$allowTargetEdit = false; $this->unlock(); $cache = wfGetCache(CACHE_ANYTHING); $key = wfMemcKey('translate-pt-move', $base); $count = $cache->decr($key); $last = strval($count) === '0'; if ($last) { $cache->delete($key); $params = array('target' => $this->params['base-target']); $entry = new ManualLogEntry('pagetranslation', 'moveok'); $entry->setPerformer($doer); $entry->setParameters($params); $entry->setTarget(Title::newFromText($base)); $logid = $entry->insert(); $entry->publish($logid); PageTranslationHooks::$jobQueueRunning = false; } $wgUser = $oldUser; return true; }
/** * Create new Log entry * * @param string $action Action name as defined above * @param integer $mapId Map id * @param string $comment Comment * @param array $params Additional params * @return ManualLogEntry */ public static function newLogEntry($action, $user, $mapId, $comment, $params = []) { $logEntry = new ManualLogEntry(self::LOG_TYPE_NAME, $action); $logEntry->setPerformer($user); $logEntry->setTarget(SpecialPage::getTitleFor(WikiaMapsSpecialController::PAGE_NAME, $mapId)); $logEntry->setComment($comment); if (!empty($params)) { // we can't allow to pass those elements // more info: https://www.mediawiki.org/wiki/Manual:Logging_to_Special:Log#1.19_and_later unset($params[1], $params[2], $params[3]); $logEntry->setParameters($params); } return $logEntry; }
/** * Create a log entry using the provided info. * Takes care about the logging interface changes in MediaWiki 1.19. * * @since 0.1 * * @param array $info */ public static function log(array $info) { $user = array_key_exists('user', $info) ? $info['user'] : $GLOBALS['wgUser']; $logEntry = new ManualLogEntry($info['type'], $info['subtype']); $logEntry->setPerformer($user); $logEntry->setTarget($info['title']); if (array_key_exists('comment', $info)) { $logEntry->setComment($info['comment']); } if (array_key_exists('parameters', $info)) { $logEntry->setParameters($info['parameters']); } $logid = $logEntry->insert(); $logEntry->publish($logid); }
/** * Called just after a new Article is created. * * @since 0.1 */ public static function onArticleInsertComplete(&$article, User &$user, $text, $summary, $minoredit, $watchthis, $sectionanchor, &$flags, Revision $revision) { global $articleProtectionNS; if (!in_array($article->getTitle()->getNamespace(), $articleProtectionNS)) { return true; } $dbw = wfGetDB(DB_MASTER); $dbw->insert('article_protection', array('article_id' => $article->getID(), 'user_name' => $user->getName(), 'owner' => 1, 'original_owner' => 1, 'edit_permission' => 0)); $logEntry = new ManualLogEntry('ArticleProtection', 'owner-created-permissions'); $logEntry->setPerformer($user); // User object, the user who performed this action $logEntry->setTarget(Title::newFromID($article->getID())); // The page that this log entry affects, a Title object $logid = $logEntry->insert(); return true; }
function run() { // Initialization $title = $this->title; // Other stuff $user = $this->getUser(); $summary = $this->getSummary(); $base = $this->getBase(); $doer = User::newFromName($this->getPerformer()); PageTranslationHooks::$allowTargetEdit = true; $error = ''; $wikipage = new WikiPage($title); $ok = $wikipage->doDeleteArticle($summary, false, 0, true, $error, $user); if (!$ok) { $params = array('target' => $base, 'error' => $ok); $type = $this->getFull() ? 'deletefnok' : 'deletelnok'; $entry = new ManualLogEntry('pagetranslation', $type); $entry->setPerformer($doer); $entry->setTarget($title); $entry->setParameters($params); $logid = $entry->insert(); $entry->publish($logid); } PageTranslationHooks::$allowTargetEdit = false; $cache = wfGetCache(CACHE_DB); $pages = (array) $cache->get(wfMemcKey('pt-base', $base)); $lastitem = array_pop($pages); if ($title->getPrefixedText() === $lastitem) { $cache->delete(wfMemcKey('pt-base', $base)); $type = $this->getFull() ? 'deletefok' : 'deletelok'; $entry = new ManualLogEntry('pagetranslation', $type); $entry->setPerformer($doer); $entry->setTarget(Title::newFromText($base)); $logid = $entry->insert(); $entry->publish($logid); $tpage = TranslatablePage::newFromTitle($title); $tpage->getTranslationPercentages(true); foreach ($tpage->getTranslationPages() as $page) { $page->invalidateCache(); } $title->invalidateCache(); } return true; }
function onSubmitInput(array $params) { if (!$this->getUser()->isAllowed('managewiki')) { throw new MWException("User '{$this->getUser()->getName()}' without managewiki right tried to change wiki settings!"); } $values = array('wiki_sitename' => $params['sitename'], 'wiki_language' => $params['language'], 'wiki_closed' => $params['closed'] == true ? 1 : 0); if ($this->getUser()->isAllowed('managewiki-restricted')) { $values['wiki_private'] = $params['private'] == true ? 1 : 0; } $dbw = wfGetDB(DB_MASTER); $dbw->update('cw_wikis', $values, array('wiki_dbname' => $params['dbname']), __METHOD__); $farmerLogEntry = new ManualLogEntry('farmer', 'managewiki'); $farmerLogEntry->setPerformer($this->getUser()); $farmerLogEntry->setTarget($this->getTitle()); $farmerLogEntry->setComment($params['reason']); $farmerLogEntry->setParameters(array('4::wiki' => $params['dbname'])); $farmerLogID = $farmerLogEntry->insert(); $farmerLogEntry->publish($farmerLogID); $this->getOutput()->addHTML('<div class="successbox">' . wfMessage('managewiki-success')->escaped() . '</div>'); return true; }
public static function changeState(MessageGroup $group, $code, $newState, User $user) { $currentState = self::getState($group, $code); if ($currentState === $newState) { return false; } $table = 'translate_groupreviews'; $index = array('tgr_group', 'tgr_language'); $row = array('tgr_group' => $group->getId(), 'tgr_lang' => $code, 'tgr_state' => $newState); $dbw = wfGetDB(DB_MASTER); $dbw->replace($table, array($index), $row, __METHOD__); $entry = new ManualLogEntry('translationreview', 'group'); $entry->setPerformer($user); $entry->setTarget(SpecialPage::getTitleFor('Translate', $group->getId())); // @todo // $entry->setComment( $comment ); $entry->setParameters(array('4::language' => $code, '5::group-label' => $group->getLabel(), '6::old-state' => $currentState, '7::new-state' => $newState)); $logid = $entry->insert(); $entry->publish($logid); Hooks::run('TranslateEventMessageGroupStateChange', array($group, $code, $currentState, $newState)); return true; }
private function doImport(array $json) { global $wgTriggerFlowThreadHooks; $wgTriggerFlowThreadHooks = false; $output = $this->getOutput(); foreach ($json as $articles) { $title = \Title::newFromText($articles->title); $count = count($articles->posts); $skipped = 0; // Skip non-existent title if ($title === null || !$title->exists()) { $output->addWikiMsg('flowthreadimport-failed', $articles->title, $count); continue; } $titleId = $title->getArticleID(); foreach ($articles->posts as $postJson) { $data = array('id' => UUID::fromHex($postJson->id), 'pageid' => $titleId, 'userid' => $postJson->userid, 'username' => $postJson->username, 'text' => $postJson->text, 'parentid' => $postJson->parentid ? UUID::fromHex($postJson->parentid) : null, 'status' => $postJson->status, 'like' => 0, 'report' => 0); $postObject = new Post($data); try { $postObject->post(); } catch (\Exception $ex) { $count--; $skipped++; } } if ($count) { $logEntry = new \ManualLogEntry('comments', 'import'); $logEntry->setPerformer($this->getUser()); $logEntry->setTarget($title); $logEntry->setParameters(array('4::count' => $count)); $logId = $logEntry->insert(); $logEntry->publish($logId, 'udp'); $output->addWikiMsg('flowthreadimport-success', $articles->title, $count); } if ($skipped) { $output->addWikiMsg('flowthreadimport-skipped', $articles->title, $skipped); } } }
/** * Record a log event for a change being patrolled * * @param $rc Mixed: change identifier or RecentChange object * @param $auto Boolean: was this patrol event automatic? * * @return bool */ public static function record($rc, $auto = false) { if (!$rc instanceof RecentChange) { $rc = RecentChange::newFromId($rc); if (!is_object($rc)) { return false; } } $title = Title::makeTitleSafe($rc->getAttribute('rc_namespace'), $rc->getAttribute('rc_title')); if ($title) { $entry = new ManualLogEntry('patrol', 'patrol'); $entry->setTarget($title); $entry->setParameters(self::buildParams($rc, $auto)); $entry->setPerformer(User::newFromName($rc->getAttribute('rc_user_text'), false)); $logid = $entry->insert(); if (!$auto) { $entry->publish($logid, 'udp'); } return true; } return false; }
/** * Create a log entry using the provided info. * Takes care about the logging interface changes in MediaWiki 1.19. * * @since 0.1 * * @param array $info */ public static function log(array $info) { $user = array_key_exists('user', $info) ? $info['user'] : $GLOBALS['wgUser']; if ($info !== false) { if (class_exists('ManualLogEntry')) { $logEntry = new ManualLogEntry($info['type'], $info['subtype']); $logEntry->setPerformer($user); $logEntry->setTarget($info['title']); if (array_key_exists('comment', $info)) { $logEntry->setComment($info['comment']); } if (array_key_exists('parameters', $info)) { $logEntry->setParameters($info['parameters']); } $logid = $logEntry->insert(); $logEntry->publish($logid); } else { // Compatibility with MediaWiki 1.18. $log = new LogPage($info['type']); $log->addEntry($info['subtype'], $info['title'], array_key_exists('comment', $info) ? $info['comment'] : '', array_key_exists('parameters', $info) ? $info['parameters'] : array(), $user); } } }
/** * Back-end article deletion * Deletes the article with database consistency, writes logs, purges caches * * @since 1.19 * * @param string $reason delete reason for deletion log * @param $suppress boolean suppress all revisions and log the deletion in * the suppression log instead of the deletion log * @param int $id article ID * @param $commit boolean defaults to true, triggers transaction end * @param &$error Array of errors to append to * @param $user User The deleting user * @return Status: Status object; if successful, $status->value is the log_id of the * deletion log entry. If the page couldn't be deleted because it wasn't * found, $status is a non-fatal 'cannotdelete' error */ public function doDeleteArticleReal( $reason, $suppress = false, $id = 0, $commit = true, &$error = '', User $user = null ) { global $wgUser, $wgContentHandlerUseDB; wfDebug( __METHOD__ . "\n" ); $status = Status::newGood(); if ( $this->mTitle->getDBkey() === '' ) { $status->error( 'cannotdelete', wfEscapeWikiText( $this->getTitle()->getPrefixedText() ) ); return $status; } $user = is_null( $user ) ? $wgUser : $user; if ( ! wfRunHooks( 'ArticleDelete', array( &$this, &$user, &$reason, &$error, &$status ) ) ) { if ( $status->isOK() ) { // Hook aborted but didn't set a fatal status $status->fatal( 'delete-hook-aborted' ); } return $status; } if ( $id == 0 ) { $this->loadPageData( 'forupdate' ); $id = $this->getID(); if ( $id == 0 ) { $status->error( 'cannotdelete', wfEscapeWikiText( $this->getTitle()->getPrefixedText() ) ); return $status; } } // Bitfields to further suppress the content if ( $suppress ) { $bitfield = 0; // This should be 15... $bitfield |= Revision::DELETED_TEXT; $bitfield |= Revision::DELETED_COMMENT; $bitfield |= Revision::DELETED_USER; $bitfield |= Revision::DELETED_RESTRICTED; } else { $bitfield = 'rev_deleted'; } // we need to remember the old content so we can use it to generate all deletion updates. $content = $this->getContent( Revision::RAW ); $dbw = wfGetDB( DB_MASTER ); $dbw->begin( __METHOD__ ); // For now, shunt the revision data into the archive table. // Text is *not* removed from the text table; bulk storage // is left intact to avoid breaking block-compression or // immutable storage schemes. // // For backwards compatibility, note that some older archive // table entries will have ar_text and ar_flags fields still. // // In the future, we may keep revisions and mark them with // the rev_deleted field, which is reserved for this purpose. $row = array( 'ar_namespace' => 'page_namespace', 'ar_title' => 'page_title', 'ar_comment' => 'rev_comment', 'ar_user' => 'rev_user', 'ar_user_text' => 'rev_user_text', 'ar_timestamp' => 'rev_timestamp', 'ar_minor_edit' => 'rev_minor_edit', 'ar_rev_id' => 'rev_id', 'ar_parent_id' => 'rev_parent_id', 'ar_text_id' => 'rev_text_id', 'ar_text' => '\'\'', // Be explicit to appease 'ar_flags' => '\'\'', // MySQL's "strict mode"... 'ar_len' => 'rev_len', 'ar_page_id' => 'page_id', 'ar_deleted' => $bitfield, 'ar_sha1' => 'rev_sha1', ); if ( $wgContentHandlerUseDB ) { $row['ar_content_model'] = 'rev_content_model'; $row['ar_content_format'] = 'rev_content_format'; } $dbw->insertSelect( 'archive', array( 'page', 'revision' ), $row, array( 'page_id' => $id, 'page_id = rev_page' ), __METHOD__ ); // Now that it's safely backed up, delete it $dbw->delete( 'page', array( 'page_id' => $id ), __METHOD__ ); $ok = ( $dbw->affectedRows() > 0 ); // $id could be laggy if ( !$ok ) { $dbw->rollback( __METHOD__ ); $status->error( 'cannotdelete', wfEscapeWikiText( $this->getTitle()->getPrefixedText() ) ); return $status; } if ( !$dbw->cascadingDeletes() ) { $dbw->delete( 'revision', array( 'rev_page' => $id ), __METHOD__ ); } $this->doDeleteUpdates( $id, $content ); // Log the deletion, if the page was suppressed, log it at Oversight instead $logtype = $suppress ? 'suppress' : 'delete'; $logEntry = new ManualLogEntry( $logtype, 'delete' ); $logEntry->setPerformer( $user ); $logEntry->setTarget( $this->mTitle ); $logEntry->setComment( $reason ); $logid = $logEntry->insert(); $logEntry->publish( $logid ); if ( $commit ) { $dbw->commit( __METHOD__ ); } wfRunHooks( 'ArticleDeleteComplete', array( &$this, &$user, $reason, $id, $content, $logEntry ) ); $status->value = $logid; return $status; }
/** * Restore the given (or all) text and file revisions for the page. * Once restored, the items will be removed from the archive tables. * The deletion log will be updated with an undeletion notice. * * @param array $timestamps Pass an empty array to restore all revisions, * otherwise list the ones to undelete. * @param string $comment * @param array $fileVersions * @param bool $unsuppress * @param User $user User performing the action, or null to use $wgUser * @return array(number of file revisions restored, number of image revisions * restored, log message) on success, false on failure. */ function undelete($timestamps, $comment = '', $fileVersions = array(), $unsuppress = false, User $user = null) { // If both the set of text revisions and file revisions are empty, // restore everything. Otherwise, just restore the requested items. $restoreAll = empty($timestamps) && empty($fileVersions); $restoreText = $restoreAll || !empty($timestamps); $restoreFiles = $restoreAll || !empty($fileVersions); if ($restoreFiles && $this->title->getNamespace() == NS_FILE) { $img = wfLocalFile($this->title); $img->load(File::READ_LATEST); $this->fileStatus = $img->restore($fileVersions, $unsuppress); if (!$this->fileStatus->isOK()) { return false; } $filesRestored = $this->fileStatus->successCount; } else { $filesRestored = 0; } if ($restoreText) { $this->revisionStatus = $this->undeleteRevisions($timestamps, $unsuppress, $comment); if (!$this->revisionStatus->isOK()) { return false; } $textRestored = $this->revisionStatus->getValue(); } else { $textRestored = 0; } // Touch the log! if ($textRestored && $filesRestored) { $reason = wfMessage('undeletedrevisions-files')->numParams($textRestored, $filesRestored)->inContentLanguage()->text(); } elseif ($textRestored) { $reason = wfMessage('undeletedrevisions')->numParams($textRestored)->inContentLanguage()->text(); } elseif ($filesRestored) { $reason = wfMessage('undeletedfiles')->numParams($filesRestored)->inContentLanguage()->text(); } else { wfDebug("Undelete: nothing undeleted...\n"); return false; } if (trim($comment) != '') { $reason .= wfMessage('colon-separator')->inContentLanguage()->text() . $comment; } if ($user === null) { global $wgUser; $user = $wgUser; } $logEntry = new ManualLogEntry('delete', 'restore'); $logEntry->setPerformer($user); $logEntry->setTarget($this->title); $logEntry->setComment($reason); Hooks::run('ArticleUndeleteLogEntry', array($this, &$logEntry, $user)); $logid = $logEntry->insert(); $logEntry->publish($logid); return array($textRestored, $filesRestored, $reason); }
/** * Backend implementation of doRollback(), please refer there for parameter * and return value documentation * * NOTE: This function does NOT check ANY permissions, it just commits the * rollback to the DB. Therefore, you should only call this function direct- * ly if you want to use custom permissions checks. If you don't, use * doRollback() instead. * @param string $fromP Name of the user whose edits to rollback. * @param string $summary Custom summary. Set to default summary if empty. * @param bool $bot If true, mark all reverted edits as bot. * * @param array $resultDetails Contains result-specific array of additional values * @param User $guser The user performing the rollback * @param array|null $tags Change tags to apply to the rollback * Callers are responsible for permission checks * (with ChangeTags::canAddTagsAccompanyingChange) * * @return array */ public function commitRollback($fromP, $summary, $bot, &$resultDetails, User $guser, $tags = null) { global $wgUseRCPatrol, $wgContLang; $dbw = wfGetDB(DB_MASTER); if (wfReadOnly()) { return [['readonlytext']]; } // Get the last editor $current = $this->getRevision(); if (is_null($current)) { // Something wrong... no page? return [['notanarticle']]; } $from = str_replace('_', ' ', $fromP); // User name given should match up with the top revision. // If the user was deleted then $from should be empty. if ($from != $current->getUserText()) { $resultDetails = ['current' => $current]; return [['alreadyrolled', htmlspecialchars($this->mTitle->getPrefixedText()), htmlspecialchars($fromP), htmlspecialchars($current->getUserText())]]; } // Get the last edit not by this person... // Note: these may not be public values $user = intval($current->getUser(Revision::RAW)); $user_text = $dbw->addQuotes($current->getUserText(Revision::RAW)); $s = $dbw->selectRow('revision', ['rev_id', 'rev_timestamp', 'rev_deleted'], ['rev_page' => $current->getPage(), "rev_user != {$user} OR rev_user_text != {$user_text}"], __METHOD__, ['USE INDEX' => 'page_timestamp', 'ORDER BY' => 'rev_timestamp DESC']); if ($s === false) { // No one else ever edited this page return [['cantrollback']]; } elseif ($s->rev_deleted & Revision::DELETED_TEXT || $s->rev_deleted & Revision::DELETED_USER) { // Only admins can see this text return [['notvisiblerev']]; } // Generate the edit summary if necessary $target = Revision::newFromId($s->rev_id, Revision::READ_LATEST); if (empty($summary)) { if ($from == '') { // no public user name $summary = wfMessage('revertpage-nouser'); } else { $summary = wfMessage('revertpage'); } } // Allow the custom summary to use the same args as the default message $args = [$target->getUserText(), $from, $s->rev_id, $wgContLang->timeanddate(wfTimestamp(TS_MW, $s->rev_timestamp)), $current->getId(), $wgContLang->timeanddate($current->getTimestamp())]; if ($summary instanceof Message) { $summary = $summary->params($args)->inContentLanguage()->text(); } else { $summary = wfMsgReplaceArgs($summary, $args); } // Trim spaces on user supplied text $summary = trim($summary); // Truncate for whole multibyte characters. $summary = $wgContLang->truncate($summary, 255); // Save $flags = EDIT_UPDATE | EDIT_INTERNAL; if ($guser->isAllowed('minoredit')) { $flags |= EDIT_MINOR; } if ($bot && $guser->isAllowedAny('markbotedits', 'bot')) { $flags |= EDIT_FORCE_BOT; } $targetContent = $target->getContent(); $changingContentModel = $targetContent->getModel() !== $current->getContentModel(); // Actually store the edit $status = $this->doEditContent($targetContent, $summary, $flags, $target->getId(), $guser, null, $tags); // Set patrolling and bot flag on the edits, which gets rollbacked. // This is done even on edit failure to have patrolling in that case (bug 62157). $set = []; if ($bot && $guser->isAllowed('markbotedits')) { // Mark all reverted edits as bot $set['rc_bot'] = 1; } if ($wgUseRCPatrol) { // Mark all reverted edits as patrolled $set['rc_patrolled'] = 1; } if (count($set)) { $dbw->update('recentchanges', $set, ['rc_cur_id' => $current->getPage(), 'rc_user_text' => $current->getUserText(), 'rc_timestamp > ' . $dbw->addQuotes($s->rev_timestamp)], __METHOD__); } if (!$status->isOK()) { return $status->getErrorsArray(); } // raise error, when the edit is an edit without a new version $statusRev = isset($status->value['revision']) ? $status->value['revision'] : null; if (!$statusRev instanceof Revision) { $resultDetails = ['current' => $current]; return [['alreadyrolled', htmlspecialchars($this->mTitle->getPrefixedText()), htmlspecialchars($fromP), htmlspecialchars($current->getUserText())]]; } if ($changingContentModel) { // If the content model changed during the rollback, // make sure it gets logged to Special:Log/contentmodel $log = new ManualLogEntry('contentmodel', 'change'); $log->setPerformer($guser); $log->setTarget($this->mTitle); $log->setComment($summary); $log->setParameters(['4::oldmodel' => $current->getContentModel(), '5::newmodel' => $targetContent->getModel()]); $logId = $log->insert($dbw); $log->publish($logId); } $revId = $statusRev->getId(); Hooks::run('ArticleRollbackComplete', [$this, $guser, $target, $current]); $resultDetails = ['summary' => $summary, 'current' => $current, 'target' => $target, 'newid' => $revId]; return []; }
/** * @param $actions_taken * @param $log_template * @param $action * @param $vars AbuseFilterVariableHolder * @param string $group * @return mixed */ public static function addLogEntries($actions_taken, $log_template, $action, $vars, $group = 'default') { wfProfileIn(__METHOD__); $dbw = wfGetDB(DB_MASTER); $central_log_template = array('afl_wiki' => wfWikiID()); $log_rows = array(); $central_log_rows = array(); $logged_local_filters = array(); $logged_global_filters = array(); foreach ($actions_taken as $filter => $actions) { $globalIndex = self::decodeGlobalName($filter); $thisLog = $log_template; $thisLog['afl_filter'] = $filter; $thisLog['afl_action'] = $action; $thisLog['afl_actions'] = implode(',', $actions); // Don't log if we were only throttling. if ($thisLog['afl_actions'] != 'throttle') { $log_rows[] = $thisLog; if (!$globalIndex) { $logged_local_filters[] = $filter; } // Global logging if ($globalIndex) { $title = Title::makeTitle($thisLog['afl_namespace'], $thisLog['afl_title']); $centralLog = $thisLog + $central_log_template; $centralLog['afl_filter'] = $globalIndex; $centralLog['afl_title'] = $title->getPrefixedText(); $centralLog['afl_namespace'] = 0; $central_log_rows[] = $centralLog; $logged_global_filters[] = $globalIndex; } } } if (!count($log_rows)) { wfProfileOut(__METHOD__); return; } // Only store the var dump if we're actually going to add log rows. $var_dump = self::storeVarDump($vars); $var_dump = "stored-text:{$var_dump}"; // To distinguish from stuff stored directly wfProfileIn(__METHOD__ . '-hitstats'); global $wgMemc; // Increment trigger counter $wgMemc->incr(self::filterMatchesKey()); $local_log_ids = array(); global $wgAbuseFilterNotifications, $wgAbuseFilterNotificationsPrivate; foreach ($log_rows as $data) { $data['afl_var_dump'] = $var_dump; $data['afl_id'] = $dbw->nextSequenceValue('abuse_filter_log_afl_id_seq'); $dbw->insert('abuse_filter_log', $data, __METHOD__); $local_log_ids[] = $dbw->insertId(); if ($data['afl_id'] === null) { $data['afl_id'] = $dbw->insertId(); } $entry = new ManualLogEntry('abusefilter', 'hit'); // Construct a user object $user = User::newFromId($data['afl_user']); $user->setName($data['afl_user_text']); $entry->setPerformer($user); // Set action target $entry->setTarget(Title::makeTitle($data['afl_namespace'], $data['afl_title'])); // Additional info $entry->setParameters(array('action' => $data['afl_action'], 'filter' => $data['afl_filter'], 'actions' => $data['afl_actions'], 'log' => $data['afl_id'])); // Send data to CheckUser if installed and we // aren't already sending a notification to recentchanges // Requires MW 1.23+ if (is_callable('CheckUserHooks::updateCheckUserData') && is_callable('ManualLogEntry::getRecentChange') && strpos($wgAbuseFilterNotifications, 'rc') === false) { $rc = $entry->getRecentChange(); CheckUserHooks::updateCheckUserData($rc); } if ($wgAbuseFilterNotifications !== false) { if (self::filterHidden($data['afl_filter']) && !$wgAbuseFilterNotificationsPrivate) { continue; } $entry->publish(0, $wgAbuseFilterNotifications); } } $method = __METHOD__; if (count($logged_local_filters)) { // Update hit-counter. $dbw->onTransactionPreCommitOrIdle(function () use($dbw, $logged_local_filters, $method) { $dbw->update('abuse_filter', array('af_hit_count=af_hit_count+1'), array('af_id' => $logged_local_filters), $method); }); } $global_log_ids = array(); // Global stuff if (count($logged_global_filters)) { $vars->computeDBVars(); $global_var_dump = self::storeVarDump($vars, true); $global_var_dump = "stored-text:{$global_var_dump}"; foreach ($central_log_rows as $index => $data) { $central_log_rows[$index]['afl_var_dump'] = $global_var_dump; } global $wgAbuseFilterCentralDB; $fdb = wfGetDB(DB_MASTER, array(), $wgAbuseFilterCentralDB); foreach ($central_log_rows as $row) { $fdb->insert('abuse_filter_log', $row, __METHOD__); $global_log_ids[] = $dbw->insertId(); } $fdb->onTransactionPreCommitOrIdle(function () use($fdb, $logged_global_filters, $method) { $fdb->update('abuse_filter', array('af_hit_count=af_hit_count+1'), array('af_id' => $logged_global_filters), $method); }); } $vars->setVar('global_log_ids', $global_log_ids); $vars->setVar('local_log_ids', $local_log_ids); // Check for emergency disabling. $total = $wgMemc->get(AbuseFilter::filterUsedKey($group)); self::checkEmergencyDisable($group, $logged_local_filters, $total); wfProfileOut(__METHOD__ . '-hitstats'); wfProfileOut(__METHOD__); }
/** * @param array $formData * @param HtmlForm $form * * @return bool|string * @throws DBUnexpectedError * @throws Exception * @throws MWException */ public static function processInput(array $formData, HtmlForm $form) { error_reporting(0); global $wgCreateWikiSQLfiles, $IP; $DBname = $formData['dbname']; $founderName = $formData['founder']; $dbw = wfGetDB(DB_MASTER); $dbTest = $dbw->query('SHOW DATABASES LIKE ' . $dbw->addQuotes($DBname) . ';'); $rows = $dbTest->numRows(); $dbTest->free(); if ($rows !== 0) { return wfMessage('createwiki-error-dbexists')->plain(); } $farmerLogEntry = new ManualLogEntry('farmer', 'createandpromote'); $farmerLogEntry->setPerformer($form->getUser()); $farmerLogEntry->setTarget($form->getTitle()); $farmerLogEntry->setComment($formData['comment']); $farmerLogEntry->setParameters(array('4::wiki' => $DBname, '5::founder' => $founderName)); $farmerLogID = $farmerLogEntry->insert(); $farmerLogEntry->publish($farmerLogID); $dbw->query('SET storage_engine=InnoDB;'); $dbw->query('CREATE DATABASE ' . $dbw->addIdentifierQuotes($DBname) . ';'); $dbw->selectDB($DBname); foreach ($wgCreateWikiSQLfiles as $file) { $dbw->sourceFile($file); } $dbw->insert('site_stats', array('ss_row_id' => 1)); $dbw->close(); // Add DNS record to cloudflare global $wgCreateWikiUseCloudFlare, $wgCloudFlareUser, $wgCloudFlareKey; if ($wgCreateWikiUseCloudFlare) { $domainPrefix = substr($DBname, 0, -4); $cloudFlare = new cloudflare_api($wgCloudFlareUser, $wgCloudFlareKey); $cloudFlareResult = $cloudFlare->rec_new('orain.org', 'CNAME', $domainPrefix, 'lb.orain.org'); if (!is_object($cloudFlareResult) || $cloudFlareResult->result !== 'success') { wfDebugLog('CreateWiki', 'CloudFlare FAILED to add CNAME for ' . $domainPrefix . '.orain.org'); } else { wfDebugLog('CreateWiki', 'CloudFlare CNAME added for ' . $domainPrefix . '.orain.org'); } } // Create local account for founder (hack) $out = exec("php5 {$IP}/extensions/CentralAuth/maintenance/createLocalAccount.php " . escapeshellarg($founderName) . ' --wiki ' . escapeshellarg($DBname)); if (!strpos($out, 'created')) { return wfMessage('createwiki-error-usernotcreated')->plain(); } require_once "{$IP}/includes/UserRightsProxy.php"; // Grant founder sysop and bureaucrat rights $founderUser = UserRightsProxy::newFromName($DBname, $founderName); $newGroups = array('sysop', 'bureaucrat'); array_map(array($founderUser, 'addGroup'), $newGroups); $founderUser->invalidateCache(); $form->getOutput()->addWikiMsg('createwiki-success', $DBname); return true; }
/** * Writes a tag action into the tag management log. * * @param string $action * @param string $tag * @param string $reason * @param User $user Who to attribute the action to * @param int $tagCount For deletion only, how many usages the tag had before * it was deleted. * @return int ID of the inserted log entry * @since 1.25 */ protected static function logTagManagementAction($action, $tag, $reason, User $user, $tagCount = null) { $dbw = wfGetDB(DB_MASTER); $logEntry = new ManualLogEntry('managetags', $action); $logEntry->setPerformer($user); // target page is not relevant, but it has to be set, so we just put in // the title of Special:Tags $logEntry->setTarget(Title::newFromText('Special:Tags')); $logEntry->setComment($reason); $params = array('4::tag' => $tag); if (!is_null($tagCount)) { $params['5:number:count'] = $tagCount; } $logEntry->setParameters($params); $logEntry->setRelations(array('Tag' => $tag)); $logId = $logEntry->insert($dbw); $logEntry->publish($logId); return $logId; }
/** * Record a file upload in the upload log and the image table * @param string $oldver * @param string $comment * @param string $pageText * @param bool|array $props * @param string|bool $timestamp * @param null|User $user * @return bool */ function recordUpload2($oldver, $comment, $pageText, $props = false, $timestamp = false, $user = null) { wfProfileIn(__METHOD__); if (is_null($user)) { global $wgUser; $user = $wgUser; } $dbw = $this->repo->getMasterDB(); $dbw->begin(__METHOD__); if (!$props) { wfProfileIn(__METHOD__ . '-getProps'); $props = $this->repo->getFileProps($this->getVirtualUrl()); wfProfileOut(__METHOD__ . '-getProps'); } if ($timestamp === false) { $timestamp = $dbw->timestamp(); } $props['description'] = $comment; $props['user'] = $user->getId(); $props['user_text'] = $user->getName(); $props['timestamp'] = wfTimestamp(TS_MW, $timestamp); // DB -> TS_MW $this->setProps($props); # Fail now if the file isn't there if (!$this->fileExists) { wfDebug(__METHOD__ . ": File " . $this->getRel() . " went missing!\n"); wfProfileOut(__METHOD__); return false; } $reupload = false; # Test to see if the row exists using INSERT IGNORE # This avoids race conditions by locking the row until the commit, and also # doesn't deadlock. SELECT FOR UPDATE causes a deadlock for every race condition. $dbw->insert('image', array('img_name' => $this->getName(), 'img_size' => $this->size, 'img_width' => intval($this->width), 'img_height' => intval($this->height), 'img_bits' => $this->bits, 'img_media_type' => $this->media_type, 'img_major_mime' => $this->major_mime, 'img_minor_mime' => $this->minor_mime, 'img_timestamp' => $timestamp, 'img_description' => $comment, 'img_user' => $user->getId(), 'img_user_text' => $user->getName(), 'img_metadata' => $dbw->encodeBlob($this->metadata), 'img_sha1' => $this->sha1), __METHOD__, 'IGNORE'); if ($dbw->affectedRows() == 0) { # (bug 34993) Note: $oldver can be empty here, if the previous # version of the file was broken. Allow registration of the new # version to continue anyway, because that's better than having # an image that's not fixable by user operations. $reupload = true; # Collision, this is an update of a file # Insert previous contents into oldimage $dbw->insertSelect('oldimage', 'image', array('oi_name' => 'img_name', 'oi_archive_name' => $dbw->addQuotes($oldver), 'oi_size' => 'img_size', 'oi_width' => 'img_width', 'oi_height' => 'img_height', 'oi_bits' => 'img_bits', 'oi_timestamp' => 'img_timestamp', 'oi_description' => 'img_description', 'oi_user' => 'img_user', 'oi_user_text' => 'img_user_text', 'oi_metadata' => 'img_metadata', 'oi_media_type' => 'img_media_type', 'oi_major_mime' => 'img_major_mime', 'oi_minor_mime' => 'img_minor_mime', 'oi_sha1' => 'img_sha1'), array('img_name' => $this->getName()), __METHOD__); # Update the current image row $dbw->update('image', array('img_size' => $this->size, 'img_width' => intval($this->width), 'img_height' => intval($this->height), 'img_bits' => $this->bits, 'img_media_type' => $this->media_type, 'img_major_mime' => $this->major_mime, 'img_minor_mime' => $this->minor_mime, 'img_timestamp' => $timestamp, 'img_description' => $comment, 'img_user' => $user->getId(), 'img_user_text' => $user->getName(), 'img_metadata' => $dbw->encodeBlob($this->metadata), 'img_sha1' => $this->sha1), array('img_name' => $this->getName()), __METHOD__); } else { # This is a new file, so update the image count DeferredUpdates::addUpdate(SiteStatsUpdate::factory(array('images' => 1))); } $descTitle = $this->getTitle(); $wikiPage = new WikiFilePage($descTitle); $wikiPage->setFile($this); # Add the log entry $action = $reupload ? 'overwrite' : 'upload'; $logEntry = new ManualLogEntry('upload', $action); $logEntry->setPerformer($user); $logEntry->setComment($comment); $logEntry->setTarget($descTitle); // Allow people using the api to associate log entries with the upload. // Log has a timestamp, but sometimes different from upload timestamp. $logEntry->setParameters(array('img_sha1' => $this->sha1, 'img_timestamp' => $timestamp)); // Note we keep $logId around since during new image // creation, page doesn't exist yet, so log_page = 0 // but we want it to point to the page we're making, // so we later modify the log entry. // For a similar reason, we avoid making an RC entry // now and wait until the page exists. $logId = $logEntry->insert(); $exists = $descTitle->exists(); if ($exists) { // Page exists, do RC entry now (otherwise we wait for later). $logEntry->publish($logId); } wfProfileIn(__METHOD__ . '-edit'); if ($exists) { # Create a null revision $latest = $descTitle->getLatestRevID(); $editSummary = LogFormatter::newFromEntry($logEntry)->getPlainActionText(); $nullRevision = Revision::newNullRevision($dbw, $descTitle->getArticleID(), $editSummary, false); if (!is_null($nullRevision)) { $nullRevision->insertOn($dbw); wfRunHooks('NewRevisionFromEditComplete', array($wikiPage, $nullRevision, $latest, $user)); $wikiPage->updateRevisionOn($dbw, $nullRevision); } } # Commit the transaction now, in case something goes wrong later # The most important thing is that files don't get lost, especially archives # NOTE: once we have support for nested transactions, the commit may be moved # to after $wikiPage->doEdit has been called. $dbw->commit(__METHOD__); # Save to memcache. # We shall not saveToCache before the commit since otherwise # in case of a rollback there is an usable file from memcached # which in fact doesn't really exist (bug 24978) $this->saveToCache(); if ($exists) { # Invalidate the cache for the description page $descTitle->invalidateCache(); $descTitle->purgeSquid(); } else { # New file; create the description page. # There's already a log entry, so don't make a second RC entry # Squid and file cache for the description page are purged by doEditContent. $content = ContentHandler::makeContent($pageText, $descTitle); $status = $wikiPage->doEditContent($content, $comment, EDIT_NEW | EDIT_SUPPRESS_RC, false, $user); $dbw->begin(__METHOD__); // XXX; doEdit() uses a transaction // Now that the page exists, make an RC entry. $logEntry->publish($logId); if (isset($status->value['revision'])) { $dbw->update('logging', array('log_page' => $status->value['revision']->getPage()), array('log_id' => $logId), __METHOD__); } $dbw->commit(__METHOD__); // commit before anything bad can happen } wfProfileOut(__METHOD__ . '-edit'); if ($reupload) { # Delete old thumbnails wfProfileIn(__METHOD__ . '-purge'); $this->purgeThumbnails(); wfProfileOut(__METHOD__ . '-purge'); # Remove the old file from the squid cache SquidUpdate::purge(array($this->getURL())); } # Hooks, hooks, the magic of hooks... wfProfileIn(__METHOD__ . '-hooks'); wfRunHooks('FileUpload', array($this, $reupload, $descTitle->exists())); wfProfileOut(__METHOD__ . '-hooks'); # Invalidate cache for all pages using this file $update = new HTMLCacheUpdate($this->getTitle(), 'imagelinks'); $update->doUpdate(); if (!$reupload) { LinksUpdate::queueRecursiveJobsForTable($this->getTitle(), 'imagelinks'); } wfProfileOut(__METHOD__); return true; }
/** * Add a newuser log entry for this user. * Before 1.19 the return value was always true. * * @param string|bool $action Account creation type. * - String, one of the following values: * - 'create' for an anonymous user creating an account for himself. * This will force the action's performer to be the created user itself, * no matter the value of $wgUser * - 'create2' for a logged in user creating an account for someone else * - 'byemail' when the created user will receive its password by e-mail * - 'autocreate' when the user is automatically created (such as by CentralAuth). * - Boolean means whether the account was created by e-mail (deprecated): * - true will be converted to 'byemail' * - false will be converted to 'create' if this object is the same as * $wgUser and to 'create2' otherwise * * @param string $reason User supplied reason * * @return int|bool True if not $wgNewUserLog; otherwise ID of log item or 0 on failure */ public function addNewUserLogEntry($action = false, $reason = '') { global $wgUser, $wgNewUserLog; if (empty($wgNewUserLog)) { return true; // disabled } if ($action === true) { $action = 'byemail'; } elseif ($action === false) { if ($this->equals($wgUser)) { $action = 'create'; } else { $action = 'create2'; } } if ($action === 'create' || $action === 'autocreate') { $performer = $this; } else { $performer = $wgUser; } $logEntry = new ManualLogEntry('newusers', $action); $logEntry->setPerformer($performer); $logEntry->setTarget($this->getUserPage()); $logEntry->setComment($reason); $logEntry->setParameters(array('4::userid' => $this->getId())); $logid = $logEntry->insert(); if ($action !== 'autocreate') { $logEntry->publish($logid); } return (int) $logid; }
/** * * @param array $data * @return bool */ public function onSubmit(array $data) { $title = Title::newFromText($data['pagename']); // Check if title is valid if (!$title) { return false; } // Get the default language for the wiki // Returns the default since the page is not loaded from DB $defLang = $title->getPageLanguage()->getCode(); $pageId = $title->getArticleID(); // Check if article exists if (!$pageId) { return false; } // Load the page language from DB $dbw = wfGetDB(DB_MASTER); $langOld = $dbw->selectField('page', 'page_lang', array('page_id' => $pageId), __METHOD__); // Url to redirect to after the operation $this->goToUrl = $title->getFullURL(); // Check if user wants to use default language if ($data['selectoptions'] == 1) { $langNew = null; } else { $langNew = $data['language']; } // No change in language if ($langNew === $langOld) { return false; } // Hardcoded [def] if the language is set to null $logOld = $langOld ? $langOld : $defLang . '[def]'; $logNew = $langNew ? $langNew : $defLang . '[def]'; // Writing new page language to database $dbw = wfGetDB(DB_MASTER); $dbw->update('page', array('page_lang' => $langNew), array('page_id' => $pageId, 'page_lang' => $langOld), __METHOD__); if (!$dbw->affectedRows()) { return false; } // Logging change of language $logParams = array('4::oldlanguage' => $logOld, '5::newlanguage' => $logNew); $entry = new ManualLogEntry('pagelang', 'pagelang'); $entry->setPerformer($this->getUser()); $entry->setTarget($title); $entry->setParameters($logParams); $logid = $entry->insert(); $entry->publish($logid); return true; }