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);
 }
 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;
 }
 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;
 }
 /**
  * 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;
 }
 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 );
 }
Beispiel #6
0
 /**
  * Record a log event for a change being patrolled
  *
  * @param int|RecentChange $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
  * @param string|string[] $tags Change tags to add to the patrol log entry
  *   ($user should be able to add the specified tags before this is called)
  *
  * @return bool
  */
 public static function record($rc, $auto = false, User $user = null, $tags = 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;
     }
     $action = $auto ? 'autopatrol' : 'patrol';
     $entry = new ManualLogEntry('patrol', $action);
     $entry->setTarget($rc->getTitle());
     $entry->setParameters(self::buildParams($rc, $auto));
     $entry->setPerformer($user);
     $entry->setTags($tags);
     $logid = $entry->insert();
     if (!$auto) {
         $entry->publish($logid, 'udp');
     }
     return true;
 }
 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;
 }
 /**
  * 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);
 }
 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;
 }
 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);
 }
Beispiel #11
0
 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;
 }
 /**
  * @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);
 }
Beispiel #14
0
 /**
  * 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);
 }
 /**
  * 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();
 }
 /**
  * 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;
 }
 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;
 }
 /**
  * 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);
         }
     }
 }
 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;
 }
Beispiel #20
0
 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?
  * @param $user User: user performing the action or null to use $wgUser
  *
  * @return bool
  */
 public static function record($rc, $auto = false, User $user = null)
 {
     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;
 }
Beispiel #22
0
 /**
  * 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;
 }
 /**
  * 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);
 }
Beispiel #24
0
 /**
  * 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;
 }
Beispiel #27
0
 /**
  * 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;
 }
Beispiel #28
0
 /**
  * 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;
 }
Beispiel #29
0
	/**
	 * 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;
	}
Beispiel #30
0
 /**
  * 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;
 }