public function getDefinitions() { $groups = MessageGroups::getAllGroups(); $keys = array(); /** * @var $g MessageGroup */ foreach ($groups as $g) { $states = $g->getMessageGroupStates()->getStates(); foreach (array_keys($states) as $state) { $keys["Translate-workflow-state-{$state}"] = $state; } } $defs = TranslateUtils::getContents(array_keys($keys), $this->getNamespace()); foreach ($keys as $key => $state) { if (!isset($defs[$key])) { // @todo Use jobqueue $title = Title::makeTitleSafe($this->getNamespace(), $key); $page = new WikiPage($title); $content = ContentHandler::makeContent($state, $title); $page->doEditContent($content, wfMessage('translate-workflow-autocreated-summary', $state)->inContentLanguage()->text(), 0, false, FuzzyBot::getUser()); } else { // Use the wiki translation as definition if available. // getContents returns array( content, last author ) list($content, ) = $defs[$key]; $keys[$key] = $content; } } return $keys; }
/** * Add or update message contents */ function update($translation, $user) { $savePage = function ($title, $text) { $wikiPage = new WikiPage($title); $content = ContentHandler::makeContent($text, $title); $result = $wikiPage->doEditContent($content, '/* PR admin */', EDIT_FORCE_BOT); return $wikiPage; }; $savePage($this->getTitle(), $translation); }
public function createPage(Title $title) { $page = new \WikiPage($title); $pageContent = 'Content of ' . $title->getFullText(); $editMessage = 'SPL system test: create page'; if (class_exists('WikitextContent')) { $page->doEditContent(new \WikitextContent($pageContent), $editMessage); } else { $page->doEdit($pageContent, $editMessage); } }
/** * Helper function for addDBData -- adds a simple page to the database * * @param string $title Title of page to be created * @param string $lang Language and content of the created page * @param string|null $content Content of the created page, or null for a generic string */ protected function makePage($title, $lang, $content = null) { global $wgContLang; if ($content === null) { $content = $lang; } if ($lang !== $wgContLang->getCode()) { $title = "{$title}/{$lang}"; } $title = Title::newFromText($title, NS_MEDIAWIKI); $wikiPage = new WikiPage($title); $contentHandler = ContentHandler::makeContent($content, $title); $wikiPage->doEditContent($contentHandler, "{$lang} translation test case"); }
/** * Run a pageSchemasCreatePage job * @return boolean success */ function run() { wfProfileIn(__METHOD__); if (is_null($this->title)) { $this->error = wfMessage('ps-createpage-invalidtitle')->text(); wfProfileOut(__METHOD__); return false; } if (method_exists('WikiPage', 'getContent')) { // MW >= 1.21 if ($this->title->getContentModel() !== CONTENT_MODEL_WIKITEXT) { $this->error = wfMessage('ps-createpage-irregulartext', $this->title->getPrefixedDBkey())->text(); wfProfileOut(__METHOD__); return false; } $wikiPage = new WikiPage($this->title); } else { $article = new Article($this->title); if (!$article) { $this->error = wfMessage('ps-createpage-notfound', $this->title->getPrefixedDBkey())->text(); wfProfileOut(__METHOD__); return false; } } $page_text = $this->params['page_text']; // Change global $wgUser variable to the one // specified by the job only for the extent of this // replacement. global $wgUser; $actual_user = $wgUser; $wgUser = User::newFromId($this->params['user_id']); $edit_summary = wfMessage('ps-generatepages-editsummary')->inContentLanguage()->parse(); if (method_exists('WikiPage', 'getContent')) { // MW >= 1.21 $content = new WikitextContent($page_text); $wikiPage->doEditContent($content, $edit_summary); } else { $article->doEdit($page_text, $edit_summary); } $wgUser = $actual_user; wfProfileOut(__METHOD__); return true; }
/** @brief Intercept image uploads and queue them for moderation. */ public static function onUploadVerifyFile($upload, $mime, &$status) { global $wgRequest, $wgUser, $wgOut; if (ModerationCanSkip::canSkip($wgUser)) { return; } $result = $upload->validateName(); if ($result !== true) { $status = array($upload->getVerificationErrorCode($result['status'])); return; } $special = new ModerationSpecialUpload($wgRequest); $special->publicLoadRequest(); $title = $upload->getTitle(); $model = $title->getContentModel(); try { $file = $upload->stashFile($wgUser); } catch (MWException $e) { $status = array("api-error-stashfailed"); return; } $key = $file->getFileKey(); $pageText = ''; if (!$special->mForReUpload) { $pageText = $special->getInitialPageText($special->mComment, $special->mLicense, $special->mCopyrightStatus, $special->mCopyrightSource); } $content = ContentHandler::makeContent($pageText, null, $model); /* Step 1. Create a page in File namespace (it will be queued for moderation) */ $page = new WikiPage($title); $status = $page->doEditContent($content, $special->mComment, 0, $title->getLatestRevID(), $wgUser); $wgOut->redirect(''); # Disable redirection after doEditContent() /* Step 2. Populate mod_stash_key field in newly inserted row of the moderation table (to indicate that this is an upload, not just editing the text on image page) */ $dbw = wfGetDB(DB_MASTER); $dbw->update('moderation', array('mod_stash_key' => $key), array('mod_id' => ModerationEditHooks::$LastInsertId), __METHOD__); $status = array("moderation-image-queued"); }
function deleteUnneededTaskBoxTemplates() { $results = self::getQueryResults("[[Category:Page with Task]]", array('title'), true); if ($results->getCount() === 0) { return FALSE; } while ($row = $results->getNext()) { $pageTitle = $row[0]->getNextObject(); $targetTitle = Title::newFromText($pageTitle->getLongWikiText()); if (!$targetTitle instanceof Title) { throw new MWException(wfMessage('tm-error-title')); } $page = new WikiPage($targetTitle); $content = $page->getContent(); if (strpos($content->getNativeData(), '{{TaskBox}}') !== false) { $resultsTasks = self::getQueryResults("[[Category:Task(s)]] [[Entity::" . $pageTitle->getLongWikiText() . "]]", array('title'), true); if ($resultsTasks->getCount() === 0) { $newContent = new WikitextContent(str_replace('{{TaskBox}}', '', $content->getNativeData())); $page->doEditContent($newContent, wfMessage('tm-tasbox-removed'), EDIT_MINOR); } } } return TRUE; }
/** * Attempt submission (no UI) * * @param array $result Array to add statuses to, currently with the * possible keys: * - spam (string): Spam string from content if any spam is detected by * matchSpamRegex. * - sectionanchor (string): Section anchor for a section save. * - nullEdit (boolean): Set if doEditContent is OK. True if null edit, * false otherwise. * - redirect (bool): Set if doEditContent is OK. True if resulting * revision is a redirect. * @param bool $bot True if edit is being made under the bot right. * * @return Status Status object, possibly with a message, but always with * one of the AS_* constants in $status->value, * * @todo FIXME: This interface is TERRIBLE, but hard to get rid of due to * various error display idiosyncrasies. There are also lots of cases * where error metadata is set in the object and retrieved later instead * of being returned, e.g. AS_CONTENT_TOO_BIG and * AS_BLOCKED_PAGE_FOR_USER. All that stuff needs to be cleaned up some * time. */ function internalAttemptSave(&$result, $bot = false) { global $wgUser, $wgRequest, $wgParser, $wgMaxArticleSize; global $wgContentHandlerUseDB; $status = Status::newGood(); if (!Hooks::run('EditPage::attemptSave', array($this))) { wfDebug("Hook 'EditPage::attemptSave' aborted article saving\n"); $status->fatal('hookaborted'); $status->value = self::AS_HOOK_ERROR; return $status; } $spam = $wgRequest->getText('wpAntispam'); if ($spam !== '') { wfDebugLog('SimpleAntiSpam', $wgUser->getName() . ' editing "' . $this->mTitle->getPrefixedText() . '" submitted bogus field "' . $spam . '"'); $status->fatal('spamprotectionmatch', false); $status->value = self::AS_SPAM_ERROR; return $status; } try { # Construct Content object $textbox_content = $this->toEditContent($this->textbox1); } catch (MWContentSerializationException $ex) { $status->fatal('content-failed-to-parse', $this->contentModel, $this->contentFormat, $ex->getMessage()); $status->value = self::AS_PARSE_ERROR; return $status; } # Check image redirect if ($this->mTitle->getNamespace() == NS_FILE && $textbox_content->isRedirect() && !$wgUser->isAllowed('upload')) { $code = $wgUser->isAnon() ? self::AS_IMAGE_REDIRECT_ANON : self::AS_IMAGE_REDIRECT_LOGGED; $status->setResult(false, $code); return $status; } # Check for spam $match = self::matchSummarySpamRegex($this->summary); if ($match === false && $this->section == 'new') { # $wgSpamRegex is enforced on this new heading/summary because, unlike # regular summaries, it is added to the actual wikitext. if ($this->sectiontitle !== '') { # This branch is taken when the API is used with the 'sectiontitle' parameter. $match = self::matchSpamRegex($this->sectiontitle); } else { # This branch is taken when the "Add Topic" user interface is used, or the API # is used with the 'summary' parameter. $match = self::matchSpamRegex($this->summary); } } if ($match === false) { $match = self::matchSpamRegex($this->textbox1); } if ($match !== false) { $result['spam'] = $match; $ip = $wgRequest->getIP(); $pdbk = $this->mTitle->getPrefixedDBkey(); $match = str_replace("\n", '', $match); wfDebugLog('SpamRegex', "{$ip} spam regex hit [[{$pdbk}]]: \"{$match}\""); $status->fatal('spamprotectionmatch', $match); $status->value = self::AS_SPAM_ERROR; return $status; } if (!Hooks::run('EditFilter', array($this, $this->textbox1, $this->section, &$this->hookError, $this->summary))) { # Error messages etc. could be handled within the hook... $status->fatal('hookaborted'); $status->value = self::AS_HOOK_ERROR; return $status; } elseif ($this->hookError != '') { # ...or the hook could be expecting us to produce an error $status->fatal('hookaborted'); $status->value = self::AS_HOOK_ERROR_EXPECTED; return $status; } if ($wgUser->isBlockedFrom($this->mTitle, false)) { // Auto-block user's IP if the account was "hard" blocked $wgUser->spreadAnyEditBlock(); # Check block state against master, thus 'false'. $status->setResult(false, self::AS_BLOCKED_PAGE_FOR_USER); return $status; } $this->kblength = (int) (strlen($this->textbox1) / 1024); if ($this->kblength > $wgMaxArticleSize) { // Error will be displayed by showEditForm() $this->tooBig = true; $status->setResult(false, self::AS_CONTENT_TOO_BIG); return $status; } if (!$wgUser->isAllowed('edit')) { if ($wgUser->isAnon()) { $status->setResult(false, self::AS_READ_ONLY_PAGE_ANON); return $status; } else { $status->fatal('readonlytext'); $status->value = self::AS_READ_ONLY_PAGE_LOGGED; return $status; } } $changingContentModel = false; if ($this->contentModel !== $this->mTitle->getContentModel()) { if (!$wgContentHandlerUseDB) { $status->fatal('editpage-cannot-use-custom-model'); $status->value = self::AS_CANNOT_USE_CUSTOM_MODEL; return $status; } elseif (!$wgUser->isAllowed('editcontentmodel')) { $status->setResult(false, self::AS_NO_CHANGE_CONTENT_MODEL); return $status; } $changingContentModel = true; $oldContentModel = $this->mTitle->getContentModel(); } if ($this->changeTags) { $changeTagsStatus = ChangeTags::canAddTagsAccompanyingChange($this->changeTags, $wgUser); if (!$changeTagsStatus->isOK()) { $changeTagsStatus->value = self::AS_CHANGE_TAG_ERROR; return $changeTagsStatus; } } if (wfReadOnly()) { $status->fatal('readonlytext'); $status->value = self::AS_READ_ONLY_PAGE; return $status; } if ($wgUser->pingLimiter() || $wgUser->pingLimiter('linkpurge', 0)) { $status->fatal('actionthrottledtext'); $status->value = self::AS_RATE_LIMITED; return $status; } # If the article has been deleted while editing, don't save it without # confirmation if ($this->wasDeletedSinceLastEdit() && !$this->recreate) { $status->setResult(false, self::AS_ARTICLE_WAS_DELETED); return $status; } # Load the page data from the master. If anything changes in the meantime, # we detect it by using page_latest like a token in a 1 try compare-and-swap. $this->page->loadPageData('fromdbmaster'); $new = !$this->page->exists(); if ($new) { // Late check for create permission, just in case *PARANOIA* if (!$this->mTitle->userCan('create', $wgUser)) { $status->fatal('nocreatetext'); $status->value = self::AS_NO_CREATE_PERMISSION; wfDebug(__METHOD__ . ": no create permission\n"); return $status; } // Don't save a new page if it's blank or if it's a MediaWiki: // message with content equivalent to default (allow empty pages // in this case to disable messages, see bug 50124) $defaultMessageText = $this->mTitle->getDefaultMessageText(); if ($this->mTitle->getNamespace() === NS_MEDIAWIKI && $defaultMessageText !== false) { $defaultText = $defaultMessageText; } else { $defaultText = ''; } if (!$this->allowBlankArticle && $this->textbox1 === $defaultText) { $this->blankArticle = true; $status->fatal('blankarticle'); $status->setResult(false, self::AS_BLANK_ARTICLE); return $status; } if (!$this->runPostMergeFilters($textbox_content, $status, $wgUser)) { return $status; } $content = $textbox_content; $result['sectionanchor'] = ''; if ($this->section == 'new') { if ($this->sectiontitle !== '') { // Insert the section title above the content. $content = $content->addSectionHeader($this->sectiontitle); } elseif ($this->summary !== '') { // Insert the section title above the content. $content = $content->addSectionHeader($this->summary); } $this->summary = $this->newSectionSummary($result['sectionanchor']); } $status->value = self::AS_SUCCESS_NEW_ARTICLE; } else { # not $new # Article exists. Check for edit conflict. $this->page->clear(); # Force reload of dates, etc. $timestamp = $this->page->getTimestamp(); wfDebug("timestamp: {$timestamp}, edittime: {$this->edittime}\n"); if ($timestamp != $this->edittime) { $this->isConflict = true; if ($this->section == 'new') { if ($this->page->getUserText() == $wgUser->getName() && $this->page->getComment() == $this->newSectionSummary()) { // Probably a duplicate submission of a new comment. // This can happen when CDN resends a request after // a timeout but the first one actually went through. wfDebug(__METHOD__ . ": duplicate new section submission; trigger edit conflict!\n"); } else { // New comment; suppress conflict. $this->isConflict = false; wfDebug(__METHOD__ . ": conflict suppressed; new section\n"); } } elseif ($this->section == '' && Revision::userWasLastToEdit(DB_MASTER, $this->mTitle->getArticleID(), $wgUser->getId(), $this->edittime)) { # Suppress edit conflict with self, except for section edits where merging is required. wfDebug(__METHOD__ . ": Suppressing edit conflict, same user.\n"); $this->isConflict = false; } } // If sectiontitle is set, use it, otherwise use the summary as the section title. if ($this->sectiontitle !== '') { $sectionTitle = $this->sectiontitle; } else { $sectionTitle = $this->summary; } $content = null; if ($this->isConflict) { wfDebug(__METHOD__ . ": conflict! getting section '{$this->section}' for time '{$this->edittime}'" . " (article time '{$timestamp}')\n"); $content = $this->page->replaceSectionContent($this->section, $textbox_content, $sectionTitle, $this->edittime); } else { wfDebug(__METHOD__ . ": getting section '{$this->section}'\n"); $content = $this->page->replaceSectionContent($this->section, $textbox_content, $sectionTitle); } if (is_null($content)) { wfDebug(__METHOD__ . ": activating conflict; section replace failed.\n"); $this->isConflict = true; $content = $textbox_content; // do not try to merge here! } elseif ($this->isConflict) { # Attempt merge if ($this->mergeChangesIntoContent($content)) { // Successful merge! Maybe we should tell the user the good news? $this->isConflict = false; wfDebug(__METHOD__ . ": Suppressing edit conflict, successful merge.\n"); } else { $this->section = ''; $this->textbox1 = ContentHandler::getContentText($content); wfDebug(__METHOD__ . ": Keeping edit conflict, failed merge.\n"); } } if ($this->isConflict) { $status->setResult(false, self::AS_CONFLICT_DETECTED); return $status; } if (!$this->runPostMergeFilters($content, $status, $wgUser)) { return $status; } if ($this->section == 'new') { // Handle the user preference to force summaries here if (!$this->allowBlankSummary && trim($this->summary) == '') { $this->missingSummary = true; $status->fatal('missingsummary'); // or 'missingcommentheader' if $section == 'new'. Blegh $status->value = self::AS_SUMMARY_NEEDED; return $status; } // Do not allow the user to post an empty comment if ($this->textbox1 == '') { $this->missingComment = true; $status->fatal('missingcommenttext'); $status->value = self::AS_TEXTBOX_EMPTY; return $status; } } elseif (!$this->allowBlankSummary && !$content->equals($this->getOriginalContent($wgUser)) && !$content->isRedirect() && md5($this->summary) == $this->autoSumm) { $this->missingSummary = true; $status->fatal('missingsummary'); $status->value = self::AS_SUMMARY_NEEDED; return $status; } # All's well $sectionanchor = ''; if ($this->section == 'new') { $this->summary = $this->newSectionSummary($sectionanchor); } elseif ($this->section != '') { # Try to get a section anchor from the section source, redirect # to edited section if header found. # XXX: Might be better to integrate this into Article::replaceSection # for duplicate heading checking and maybe parsing. $hasmatch = preg_match("/^ *([=]{1,6})(.*?)(\\1) *\\n/i", $this->textbox1, $matches); # We can't deal with anchors, includes, html etc in the header for now, # headline would need to be parsed to improve this. if ($hasmatch && strlen($matches[2]) > 0) { $sectionanchor = $wgParser->guessLegacySectionNameFromWikiText($matches[2]); } } $result['sectionanchor'] = $sectionanchor; // Save errors may fall down to the edit form, but we've now // merged the section into full text. Clear the section field // so that later submission of conflict forms won't try to // replace that into a duplicated mess. $this->textbox1 = $this->toEditText($content); $this->section = ''; $status->value = self::AS_SUCCESS_UPDATE; } if (!$this->allowSelfRedirect && $content->isRedirect() && $content->getRedirectTarget()->equals($this->getTitle())) { // If the page already redirects to itself, don't warn. $currentTarget = $this->getCurrentContent()->getRedirectTarget(); if (!$currentTarget || !$currentTarget->equals($this->getTitle())) { $this->selfRedirect = true; $status->fatal('selfredirect'); $status->value = self::AS_SELF_REDIRECT; return $status; } } // Check for length errors again now that the section is merged in $this->kblength = (int) (strlen($this->toEditText($content)) / 1024); if ($this->kblength > $wgMaxArticleSize) { $this->tooBig = true; $status->setResult(false, self::AS_MAX_ARTICLE_SIZE_EXCEEDED); return $status; } $flags = EDIT_AUTOSUMMARY | ($new ? EDIT_NEW : EDIT_UPDATE) | ($this->minoredit && !$this->isNew ? EDIT_MINOR : 0) | ($bot ? EDIT_FORCE_BOT : 0); $doEditStatus = $this->page->doEditContent($content, $this->summary, $flags, false, $wgUser, $content->getDefaultFormat(), $this->changeTags); if (!$doEditStatus->isOK()) { // Failure from doEdit() // Show the edit conflict page for certain recognized errors from doEdit(), // but don't show it for errors from extension hooks $errors = $doEditStatus->getErrorsArray(); if (in_array($errors[0][0], array('edit-gone-missing', 'edit-conflict', 'edit-already-exists'))) { $this->isConflict = true; // Destroys data doEdit() put in $status->value but who cares $doEditStatus->value = self::AS_END; } return $doEditStatus; } $result['nullEdit'] = $doEditStatus->hasMessage('edit-no-change'); if ($result['nullEdit']) { // We don't know if it was a null edit until now, so increment here $wgUser->pingLimiter('linkpurge'); } $result['redirect'] = $content->isRedirect(); $this->updateWatchlist(); // If the content model changed, add a log entry if ($changingContentModel) { $this->addContentModelChangeLogEntry($wgUser, $oldContentModel, $this->contentModel, $this->summary); } return $status; }
function createAllPages() { $out = $this->getOutput(); $req = $this->getRequest(); $user = $this->getUser(); $template_name = trim($req->getVal("template_name")); $template_multiple = $req->getBool("template_multiple"); // If this is a multiple-instance template, there // shouldn't be a corresponding form or category. if ($template_multiple) { $form_name = null; $category_name = null; } else { $form_name = trim($req->getVal("form_name")); $category_name = trim($req->getVal("category_name")); } if ($template_name === '' || !$template_multiple && ($form_name === '' || $category_name === '')) { $out->addWikiMsg('sf_createclass_missingvalues'); return; } $fields = array(); $jobs = array(); // Cycle through all the rows passed in. for ($i = 1; $req->getVal("field_name_{$i}") != ''; $i++) { // Go through the query values, setting the appropriate // local variables. $field_name = trim($req->getVal("field_name_{$i}")); $property_name = trim($req->getVal("property_name_{$i}")); $property_type = $req->getVal("property_type_{$i}"); $allowed_values = $req->getVal("allowed_values_{$i}"); $is_list = $req->getCheck("is_list_{$i}"); // Create an SFTemplateField object based on these // values, and add it to the $fields array. $field = SFTemplateField::create($field_name, $field_name, $property_name, $is_list); if (defined('CARGO_VERSION')) { $field->setFieldType($property_type); // Hopefully it's safe to use a Cargo // utility method here. $possibleValues = CargoUtils::smartSplit(',', $allowed_values); $field->setPossibleValues($possibleValues); } $fields[] = $field; // Create the property, and make a job for it. if (defined('SMW_VERSION') && !empty($property_name)) { $full_text = SFCreateProperty::createPropertyText($property_type, '', $allowed_values); $property_title = Title::makeTitleSafe(SMW_NS_PROPERTY, $property_name); $params = array(); $params['user_id'] = $user->getId(); $params['page_text'] = $full_text; $params['edit_summary'] = wfMessage('sf_createproperty_editsummary', $property_type)->inContentLanguage()->text(); $jobs[] = new SFCreatePageJob($property_title, $params); } } // Also create the "connecting property", if there is one. $connectingProperty = trim($req->getVal('connecting_property')); if (defined('SMW_VERSION') && $connectingProperty != '') { global $smwgContLang; $datatypeLabels = $smwgContLang->getDatatypeLabels(); $property_type = $datatypeLabels['_wpg']; $full_text = SFCreateProperty::createPropertyText($property_type, '', $allowed_values); $property_title = Title::makeTitleSafe(SMW_NS_PROPERTY, $connectingProperty); $params = array(); $params['user_id'] = $user->getId(); $params['page_text'] = $full_text; $params['edit_summary'] = wfMessage('sf_createproperty_editsummary', $property_type)->inContentLanguage()->text(); $jobs[] = new SFCreatePageJob($property_title, $params); } // Create the template, and save it (might as well save // one page, instead of just creating jobs for all of them). $template_format = $req->getVal("template_format"); $sfTemplate = new SFTemplate($template_name, $fields); if (defined('CARGO_VERSION')) { $sfTemplate->mCargoTable = trim($req->getVal("cargo_table")); } if (defined('SMW_VERSION') && $template_multiple) { $sfTemplate->setConnectingProperty($connectingProperty); } else { $sfTemplate->setCategoryName($category_name); } $sfTemplate->setFormat($template_format); $full_text = $sfTemplate->createText(); $template_title = Title::makeTitleSafe(NS_TEMPLATE, $template_name); $edit_summary = ''; if (method_exists('WikiPage', 'doEditContent')) { // MW 1.21+ $template_page = new WikiPage($template_title); $content = new WikitextContent($full_text); $template_page->doEditContent($content, $edit_summary); } else { // MW <= 1.20 $template_article = new Article($template_title); $template_article->doEdit($full_text, $edit_summary); } // Create the form, and make a job for it. if ($form_name != '') { $form_template = SFTemplateInForm::create($template_name, '', false); $form_items = array(); $form_items[] = array('type' => 'template', 'name' => $form_template->getTemplateName(), 'item' => $form_template); $form = SFForm::create($form_name, $form_items); $full_text = $form->createMarkup(); $form_title = Title::makeTitleSafe(SF_NS_FORM, $form_name); $params = array(); $params['user_id'] = $user->getId(); $params['page_text'] = $full_text; $jobs[] = new SFCreatePageJob($form_title, $params); } // Create the category, and make a job for it. if ($category_name != '') { $full_text = SFCreateCategory::createCategoryText($form_name, $category_name, ''); $category_title = Title::makeTitleSafe(NS_CATEGORY, $category_name); $params = array(); $params['user_id'] = $user->getId(); $params['page_text'] = $full_text; $jobs[] = new SFCreatePageJob($category_title, $params); } if (class_exists('JobQueueGroup')) { JobQueueGroup::singleton()->push($jobs); } else { // MW <= 1.20 Job::batchInsert($jobs); } $out->addWikiMsg('sf_createclass_success'); }
/** * Adds a revision to a page, while returning the resuting text's id * * @param WikiPage $page The page to add the revision to * @param string $text The revisions text * @param string $summary The revisions summare * @return int * @throws MWException */ private function addRevision($page, $text, $summary) { $status = $page->doEditContent(ContentHandler::makeContent($text, $page->getTitle()), $summary); if ($status->isGood()) { $value = $status->getValue(); $revision = $value['revision']; $id = $revision->getTextId(); if ($id > 0) { return $id; } } throw new MWException("Could not determine text id"); }
/** * Run a replaceText job * @return boolean success */ function run() { wfProfileIn(__METHOD__); if (is_null($this->title)) { $this->error = "replaceText: Invalid title"; wfProfileOut(__METHOD__); return false; } if (array_key_exists('move_page', $this->params)) { global $wgUser; $actual_user = $wgUser; $wgUser = User::newFromId($this->params['user_id']); $cur_page_name = $this->title->getText(); if ($this->params['use_regex']) { $new_page_name = preg_replace("/" . $this->params['target_str'] . "/U", $this->params['replacement_str'], $cur_page_name); } else { $new_page_name = str_replace($this->params['target_str'], $this->params['replacement_str'], $cur_page_name); } $new_title = Title::newFromText($new_page_name, $this->title->getNamespace()); $reason = $this->params['edit_summary']; $create_redirect = $this->params['create_redirect']; $this->title->moveTo($new_title, true, $reason, $create_redirect); if ($this->params['watch_page']) { if (class_exists('WatchAction')) { // Class was added in MW 1.19 WatchAction::doWatch($new_title, $wgUser); } else { Action::factory('watch', new WikiPage($new_title))->execute(); } } $wgUser = $actual_user; } else { // WikiPage::getContent() replaced // Article::fetchContent() starting in MW 1.21. if (method_exists('WikiPage', 'getContent')) { if ($this->title->getContentModel() !== CONTENT_MODEL_WIKITEXT) { $this->error = 'replaceText: Wiki page "' . $this->title->getPrefixedDBkey() . '" does not hold regular wikitext.'; wfProfileOut(__METHOD__); return false; } $wikiPage = new WikiPage($this->title); // Is this check necessary? if (!$wikiPage) { $this->error = 'replaceText: Wiki page not found for "' . $this->title->getPrefixedDBkey() . '."'; wfProfileOut(__METHOD__); return false; } $article_text = $wikiPage->getContent()->getNativeData(); } else { $article = new Article($this->title, 0); if (!$article) { $this->error = 'replaceText: Article not found for "' . $this->title->getPrefixedDBkey() . '"'; wfProfileOut(__METHOD__); return false; } $article_text = $article->fetchContent(); } wfProfileIn(__METHOD__ . '-replace'); $target_str = $this->params['target_str']; $replacement_str = $this->params['replacement_str']; // @todo FIXME eh? $num_matches; if ($this->params['use_regex']) { $new_text = preg_replace('/' . $target_str . '/U', $replacement_str, $article_text, -1, $num_matches); } else { $new_text = str_replace($target_str, $replacement_str, $article_text, $num_matches); } // If there's at least one replacement, modify the page, // using the passed-in edit summary. if ($num_matches > 0) { // Change global $wgUser variable to the one // specified by the job only for the extent of // this replacement. global $wgUser; $actual_user = $wgUser; $wgUser = User::newFromId($this->params['user_id']); $edit_summary = $this->params['edit_summary']; $flags = EDIT_MINOR; if ($wgUser->isAllowed('bot')) { $flags |= EDIT_FORCE_BOT; } if (method_exists('WikiPage', 'getContent')) { $new_content = new WikitextContent($new_text); $wikiPage->doEditContent($new_content, $edit_summary, $flags); } else { $article->doEdit($new_text, $edit_summary, $flags); } $wgUser = $actual_user; } wfProfileOut(__METHOD__ . '-replace'); } wfProfileOut(__METHOD__); return true; }
protected function createPage($page, $text, $model = null) { if (is_string($page)) { if (!preg_match('/:/', $page) && ($model === null || $model === CONTENT_MODEL_WIKITEXT)) { $ns = $this->getDefaultWikitextNS(); $page = MWNamespace::getCanonicalName($ns) . ':' . $page; } $page = Title::newFromText($page); } if ($page instanceof Title) { $page = new WikiPage($page); } if ($page->exists()) { $page->doDeleteArticle("done"); } $content = ContentHandler::makeContent($text, $page->getTitle(), $model); $page->doEditContent($content, "testing", EDIT_NEW); return $page; }
/** * @return RecentChange */ private function getCategorizationChange($timestamp, $thisId, $lastId) { $wikiPage = new WikiPage(Title::newFromText('Testpage')); $wikiPage->doEditContent(new WikitextContent('Some random text'), 'page created'); $wikiPage = new WikiPage(Title::newFromText('Category:Foo')); $wikiPage->doEditContent(new WikitextContent('Some random text'), 'category page created'); $user = $this->getTestUser(); $recentChange = $this->testRecentChangesHelper->makeCategorizationRecentChange($user, 'Category:Foo', $wikiPage->getId(), $thisId, $lastId, $timestamp); return $recentChange; }
/** * Does the actual edit. * @param Title $title * @param string $translation * @param string $comment Edit summary. */ public function import($title, $translation, $comment) { $flags = EDIT_FORCE_BOT; if ($this->norc) { $flags |= EDIT_SUPPRESS_RC; } $this->reportProgress("Importing {$title->getPrefixedText()}: ", $title); $wikipage = new WikiPage($title); $content = ContentHandler::makeContent($translation, $title); $status = $wikipage->doEditContent($content, $comment, $flags, false, FuzzyBot::getUser()); $success = $status === true || is_object($status) && $status->isOK(); $this->reportProgress($success ? 'OK' : 'FAILED', $title); }
function approveEditById($id) { $dbw = wfGetDB(DB_MASTER); $row = $dbw->selectRow('moderation', array('mod_id AS id', 'mod_timestamp AS timestamp', 'mod_user AS user', 'mod_user_text AS user_text', 'mod_cur_id AS cur_id', 'mod_namespace AS namespace', 'mod_title AS title', 'mod_comment AS comment', 'mod_minor AS minor', 'mod_bot AS bot', 'mod_last_oldid AS last_oldid', 'mod_ip AS ip', 'mod_header_xff AS header_xff', 'mod_header_ua AS header_ua', 'mod_text AS text', 'mod_merged_revid AS merged_revid', 'mod_rejected AS rejected', 'mod_stash_key AS stash_key'), array('mod_id' => $id), __METHOD__); if (!$row) { throw new ModerationError('moderation-edit-not-found'); } if ($row->merged_revid) { throw new ModerationError('moderation-already-merged'); } if ($row->rejected && $row->timestamp < $this->mSpecial->earliestReapprovableTimestamp) { throw new ModerationError('moderation-rejected-long-ago'); } # Prepare everything $title = Title::makeTitle($row->namespace, $row->title); $model = $title->getContentModel(); $user = $row->user ? User::newFromId($row->user) : User::newFromName($row->user_text, false); $flags = EDIT_DEFER_UPDATES | EDIT_AUTOSUMMARY; if ($row->bot && $user->isAllowed('bot')) { $flags |= EDIT_FORCE_BOT; } if ($row->minor) { # doEditContent() checks the right $flags |= EDIT_MINOR; } # For CheckUser extension to work properly, IP, XFF and UA # should be set to the correct values for the original user # (not from the moderator) $cuHook = new ModerationCheckUserHook(); $cuHook->install($row->ip, $row->header_xff, $row->header_ua); $approveHook = new ModerationApproveHook(); $approveHook->install(array('rev_timestamp' => $dbw->timestamp($row->timestamp), 'rev_user' => $user->getId(), 'rev_user_text' => $user->getName())); $status = Status::newGood(); if ($row->stash_key) { # This is the upload from stash. $stash = RepoGroup::singleton()->getLocalRepo()->getUploadStash($user); try { $file = $stash->getFile($row->stash_key); } catch (MWException $e) { throw new ModerationError('moderation-missing-stashed-image'); } $upload = new UploadFromStash($user, $stash); $upload->initialize($row->stash_key, $title->getText()); $status = $upload->performUpload($row->comment, $row->text, 0, $user); } else { # This is normal edit (not an upload). $new_content = ContentHandler::makeContent($row->text, null, $model); $page = new WikiPage($title); if (!$page->exists()) { # New page $status = $page->doEditContent($new_content, $row->comment, $flags, false, $user); } else { # Existing page $latest = $page->getLatest(); if ($latest == $row->last_oldid) { # Page hasn't changed since this edit was queued for moderation. $status = $page->doEditContent($new_content, $row->comment, $flags, $row->last_oldid, $user); } else { # Page has changed! # Let's attempt merging, as MediaWiki does in private EditPage::mergeChangesIntoContent(). $base_content = $row->last_oldid ? Revision::newFromId($row->last_oldid)->getContent(Revision::RAW) : ContentHandler::makeContent('', null, $model); $latest_content = Revision::newFromId($latest)->getContent(Revision::RAW); $handler = ContentHandler::getForModelID($base_content->getModel()); $merged_content = $handler->merge3($base_content, $new_content, $latest_content); if ($merged_content) { $status = $page->doEditContent($merged_content, $row->comment, $flags, $latest, $user); } else { $dbw = wfGetDB(DB_MASTER); $dbw->update('moderation', array('mod_conflict' => 1), array('mod_id' => $id), __METHOD__); $dbw->commit(__METHOD__); throw new ModerationError('moderation-edit-conflict'); } } } } $approveHook->deinstall(); $cuHook->deinstall(); if (!$status->isGood()) { throw new ModerationError($status->getMessage()); } $logEntry = new ManualLogEntry('moderation', 'approve'); $logEntry->setPerformer($this->moderator); $logEntry->setTarget($title); $logEntry->setParameters(array('revid' => $approveHook->lastRevId)); $logid = $logEntry->insert(); $logEntry->publish($logid); # Approved edits are removed from "moderation" table, # because they already exist in page history, recentchanges etc. $dbw = wfGetDB(DB_MASTER); $dbw->delete('moderation', array('mod_id' => $id), __METHOD__); }
/** * @covers WikiPage::doRollback */ public function testDoRollbackFailureSameContent() { $admin = new User(); $admin->setName("Admin"); $admin->addGroup("sysop"); #XXX: make the test user a sysop... $text = "one"; $page = $this->newPage("WikiPageTest_testDoRollback"); $page->doEditContent(ContentHandler::makeContent($text, $page->getTitle(), CONTENT_MODEL_WIKITEXT), "section one", EDIT_NEW, false, $admin); $rev1 = $page->getRevision(); $user1 = new User(); $user1->setName("127.0.1.11"); $user1->addGroup("sysop"); #XXX: make the test user a sysop... $text .= "\n\ntwo"; $page = new WikiPage($page->getTitle()); $page->doEditContent(ContentHandler::makeContent($text, $page->getTitle(), CONTENT_MODEL_WIKITEXT), "adding section two", 0, false, $user1); # now, do a the rollback from the same user was doing the edit before $resultDetails = array(); $token = $user1->getEditToken(array($page->getTitle()->getPrefixedText(), $user1->getName()), null); $errors = $page->doRollback($user1->getName(), "testing revert same user", $token, false, $resultDetails, $admin); $this->assertEquals(array(), $errors, "Rollback failed same user"); # now, try the rollback $resultDetails = array(); $token = $admin->getEditToken(array($page->getTitle()->getPrefixedText(), $user1->getName()), null); $errors = $page->doRollback($user1->getName(), "testing revert", $token, false, $resultDetails, $admin); $this->assertEquals(array(array('alreadyrolled', 'WikiPageTest testDoRollback', '127.0.1.11', 'Admin')), $errors, "Rollback not failed"); $page = new WikiPage($page->getTitle()); $this->assertEquals($rev1->getSha1(), $page->getRevision()->getSha1(), "rollback did not revert to the correct revision"); $this->assertEquals("one", $page->getContent()->getNativeData()); }
protected function saveBodyContent() { if ($this->dirtyFlags['content']) { $wikiPage = new WikiPage($this->getTitle()); $contentObj = ContentHandler::makeContent($this->bodyContent, $wikiPage->getTitle()); $pageResult = $wikiPage->doEditContent($contentObj, '', EDIT_FORCE_BOT); } }
/** * Run a dtImport job * @return boolean success */ function run() { wfProfileIn(__METHOD__); if (is_null($this->title)) { $this->error = "dtImport: Invalid title"; wfProfileOut(__METHOD__); return false; } if (method_exists('WikiPage', 'getContent')) { $wikiPage = new WikiPage($this->title); if (!$wikiPage) { $this->error = 'dtImport: Wiki page not found "' . $this->title->getPrefixedDBkey() . '"'; wfProfileOut(__METHOD__); return false; } } else { $article = new Article($this->title); if (!$article) { $this->error = 'dtImport: Article not found "' . $this->title->getPrefixedDBkey() . '"'; wfProfileOut(__METHOD__); return false; } } $for_pages_that_exist = $this->params['for_pages_that_exist']; if ($for_pages_that_exist == 'skip' && $this->title->exists()) { return true; } // Change global $wgUser variable to the one specified by // the job only for the extent of this import. global $wgUser; $actual_user = $wgUser; $wgUser = User::newFromId($this->params['user_id']); $text = $this->params['text']; if ($this->title->exists()) { if ($for_pages_that_exist == 'append') { if (method_exists('WikiPage', 'getContent')) { // MW >= 1.21 $existingText = $wikiPage->getContent()->getNativeData(); } else { $existingText = $article->getContent(); } $text = $existingText . "\n" . $text; } elseif ($for_pages_that_exist == 'merge') { $existingPageStructure = DTPageStructure::newFromTitle($this->title); $newPageStructure = new DTPageStructure(); $newPageStructure->parsePageContents($text); $existingPageStructure->mergeInPageStructure($newPageStructure); $text = $existingPageStructure->toWikitext(); } // otherwise, $for_pages_that_exist == 'overwrite' } $edit_summary = $this->params['edit_summary']; if (method_exists('WikiPage', 'getContent')) { $new_content = new WikitextContent($text); $wikiPage->doEditContent($new_content, $edit_summary); } else { $article->doEdit($text, $edit_summary); } $wgUser = $actual_user; wfProfileOut(__METHOD__); return true; }
/** * Does the actual edit if possible. * @param Title $title * @param string $text * @param bool $dryrun Whether to really do it or just show what would be done. * @param string $comment Edit summary. */ private function updateMessage($title, $text, $dryrun, $comment = null) { global $wgTranslateDocumentationLanguageCode; $this->reportProgress("Updating {$title->getPrefixedText()}... ", $title); if (!$title instanceof Title) { $this->reportProgress("INVALID TITLE!", $title); return; } $items = explode('/', $title->getText(), 2); if (isset($items[1]) && $items[1] === $wgTranslateDocumentationLanguageCode) { $this->reportProgress("IGNORED!", $title); return; } if ($dryrun) { $this->reportProgress("DRY RUN!", $title); return; } $wikipage = new WikiPage($title); $content = ContentHandler::makeContent($text, $title); $status = $wikipage->doEditContent($content, $comment ? $comment : 'Marking as fuzzy', EDIT_FORCE_BOT | EDIT_UPDATE, false, FuzzyBot::getUser()); $success = $status === true || is_object($status) && $status->isOK(); $this->reportProgress($success ? 'OK' : 'FAILED', $title); }
public function testOnAddingAndRemovingCategoryToTemplates_embeddingPagesAreIgnored() { $this->setMwGlobals('wgCategoryCollation', 'uppercase'); $templateTitle = Title::newFromText('Template:TestingTemplate'); $templatePage = new WikiPage($templateTitle); $wikiPage = new WikiPage(Title::newFromText('Testing')); $wikiPage->doEditContent(new WikitextContent('{{TestingTemplate}}'), 'added template'); $otherWikiPage = new WikiPage(Title::newFromText('Some_other_page')); $otherWikiPage->doEditContent(new WikitextContent('{{TestingTemplate}}'), 'added template'); $templatePage->doEditContent(new WikitextContent('[[Category:Foo]]'), 'added category'); $this->assertRecentChangeByCategorization($templateTitle, $templatePage->getParserOutput(new ParserOptions()), Title::newFromText('Foo'), array(array('Foo', '[[:Template:TestingTemplate]] and 2 pages added to category'))); }
/** * @todo FIXME: the above rollback test is better, but it keeps failing in jenkins for some reason. */ public function testDoRollback() { $admin = new User(); $admin->setName("Admin"); $text = "one"; $page = $this->newPage("WikiPageTest_testDoRollback"); $page->doEditContent(ContentHandler::makeContent($text, $page->getTitle(), CONTENT_MODEL_WIKITEXT), "section one", EDIT_NEW, false, $admin); $rev1 = $page->getRevision(); $user1 = new User(); $user1->setName("127.0.1.11"); $text .= "\n\ntwo"; $page = new WikiPage($page->getTitle()); $page->doEditContent(ContentHandler::makeContent($text, $page->getTitle(), CONTENT_MODEL_WIKITEXT), "adding section two", 0, false, $user1); # now, try the rollback $admin->addGroup("sysop"); #XXX: make the test user a sysop... $token = $admin->getEditToken(array($page->getTitle()->getPrefixedText(), $user1->getName()), null); $errors = $page->doRollback($user1->getName(), "testing revert", $token, false, $details, $admin); if ($errors) { $this->fail("Rollback failed:\n" . print_r($errors, true) . ";\n" . print_r($details, true)); } $page = new WikiPage($page->getTitle()); $this->assertEquals($rev1->getSha1(), $page->getRevision()->getSha1(), "rollback did not revert to the correct revision"); $this->assertEquals("one", $page->getContent()->getNativeData()); }
public static function addCategoriesToArticle($iArticleId) { if (BsCore::checkAccessAdmission('read') === false) { return FormatJson::encode(array('success' => false)); } if (wfReadOnly()) { global $wgReadOnly; return FormatJson::encode(array('success' => false, 'msg' => wfMessage('bs-readonly', $wgReadOnly)->plain())); } $sTags = RequestContext::getMain()->getRequest()->getVal('categories'); $aTags = empty($sTags) ? array() : explode(',', $sTags); $oTitle = Title::newFromID($iArticleId); if (is_null($oTitle) || !$oTitle->exists()) { $oRequest = RequestContext::getMain()->getRequest(); $sPageName = $oRequest->getVal("page_name", ""); $oTitle = Title::newFromText($sPageName); } $sCat = BsNamespaceHelper::getNamespaceName(NS_CATEGORY); $sText = BsPageContentProvider::getInstance()->getContentFromTitle($oTitle, Revision::RAW); // Remove all before adding $sPattern = '#^\\[\\[' . $sCat . ':.*?\\]\\]#im'; $sText = preg_replace($sPattern, '', $sText); if (!empty($aTags)) { foreach ($aTags as $sTag) { $sText .= "\n[[" . $sCat . ":{$sTag}]]"; } } $oWikiPage = new WikiPage($oTitle); $oUser = RequestContext::getMain()->getUser(); $oContent = new WikitextContent($sText); $oStatus = $oWikiPage->doEditContent($oContent, "", 0, false, $oUser); if (!$oStatus->isGood()) { return FormatJson::encode(array('success' => false, 'msg' => $oStatus->getMessage())); } return FormatJson::encode(array('success' => true)); }
public function testOnAddingAndRemovingCategoryToTemplates_embeddingPagesAreIgnored() { $this->setMwGlobals('wgCategoryCollation', 'uppercase'); $templateTitle = Title::newFromText('Template:TestingTemplate'); $templatePage = new WikiPage($templateTitle); $wikiPage = new WikiPage(Title::newFromText('Testing')); $wikiPage->doEditContent(new WikitextContent('{{TestingTemplate}}'), 'added template'); $this->runAllRelatedJobs(); $otherWikiPage = new WikiPage(Title::newFromText('Some_other_page')); $otherWikiPage->doEditContent(new WikitextContent('{{TestingTemplate}}'), 'added template'); $this->runAllRelatedJobs(); $this->assertRecentChangeByCategorization($templateTitle, $templatePage->getParserOutput(new ParserOptions()), Title::newFromText('Baz'), []); $templatePage->doEditContent(new WikitextContent('[[Category:Baz]]'), 'added category'); $this->runAllRelatedJobs(); $this->assertRecentChangeByCategorization($templateTitle, $templatePage->getParserOutput(new ParserOptions()), Title::newFromText('Baz'), [['Baz', '[[:Template:TestingTemplate]] added to category, ' . '[[Special:WhatLinksHere/Template:TestingTemplate|this page is included within other pages]]']]); }
public function testRedirectPartner() { // Create Charles. $charlesTitle = Title::newFromText('Charles'); $charlesPage = new WikiPage($charlesTitle); $charlesPage->doEditContent(new WikitextContent('{{#genealogy:partner|Diana}}'), ''); $charles = new Person($charlesTitle); // Create Diana and made sure she's Charles' partner. $diannaTitle = Title::newFromText('Diana'); $diannaPage = new WikiPage($diannaTitle); $diannaPage->doEditContent(new WikitextContent("Dianna"), ''); $this->assertEquals('Diana', $charles->getPartners()['Diana']->getTitle()); // Redirect Diana to Dianna. $diannaPage->doEditContent(new WikitextContent("#REDIRECT [[Dianna]]"), 'Redirecting'); $diana = new Person(Title::newFromText('Diana')); $this->assertEquals('Dianna', $diana->getTitle()->getText()); $this->assertEquals(['Diana', 'Dianna'], array_keys($diana->getTitles())); // Check that Charles and Dianna have the expected partners. $this->assertCount(1, $charles->getPartners()); $this->assertEquals('Dianna', $charles->getPartners()['Dianna']->getTitle()); $this->assertCount(1, $diana->getPartners()); $this->assertEquals('Charles', $diana->getPartners()['Charles']->getTitle()); // Then redirect Charles and check everything again. $charlesPage->doEditContent(new WikitextContent("#REDIRECT [[King Charles]]"), ''); $kingChPage = new WikiPage(Title::newFromText('King Charles')); $kingChPage->doEditContent(new WikitextContent('{{#genealogy:partner|Diana}}'), ''); $this->assertEquals(['Charles', 'King_Charles'], array_keys($charles->getTitles())); $this->assertCount(1, $charles->getPartners()); $this->assertEquals('Dianna', $charles->getPartners()['Dianna']->getTitle()); $this->assertCount(1, $diana->getPartners()); $this->assertEquals('King Charles', $diana->getPartners()['King_Charles']->getTitle()->getText()); }