Пример #1
0
 /**
  * Fetch additional information that is related to the saving that has just happened,
  * e.g. regarding the last edit date. In runs where this hook is not triggered, the
  * last DB entry (of MW) will be used to fill such properties.
  *
  * @note This method directly accesses a member of Article that is informally declared to
  * be private. However, there is no way to otherwise access an article's parseroutput for
  * the purpose of adding information there. If the private access ever becomes a problem,
  * a global/static variable appears to be the only way to get more article data to
  * LinksUpdate.
  *
  * @param WikiPage|Article $article WikiPage on 1.19 and later
  * @param Revision $rev
  * @param integer $baseID
  * @param User $user
  *
  * @return true
  */
 public static function onNewRevisionFromEditComplete($article, Revision $rev, $baseID, User $user)
 {
     global $smwgPageSpecialProperties;
     if ($article->mPreparedEdit && $article->mPreparedEdit->output instanceof ParserOutput) {
         $output = $article->mPreparedEdit->output;
         $title = $article->getTitle();
         if (!isset($title)) {
             return true;
             // nothing we can do
         }
         if (!isset($output->mSMWData)) {
             // no data container yet, make one
             $output->mSMWData = new SMWSemanticData(new SMWDIWikiPage($title->getDBkey(), $title->getNamespace(), $title->getInterwiki()));
         }
         $semdata = $output->mSMWData;
     } else {
         // give up, just keep the old data
         return true;
     }
     if (in_array('_MDAT', $smwgPageSpecialProperties)) {
         $timestamp = $article->getTimestamp();
         $di = self::getDataItemFromMWTimestamp($timestamp);
         if (!is_null($di)) {
             $semdata->addPropertyObjectValue(new SMWDIProperty('_MDAT'), $di);
         }
     }
     if (in_array('_LEDT', $smwgPageSpecialProperties)) {
         $di = SMWDIWikiPage::newFromTitle($user->getUserPage());
         if (!is_null($di)) {
             $semdata->addPropertyObjectValue(new SMWDIProperty('_LEDT'), $di);
         }
     }
     if (in_array('_NEWP', $smwgPageSpecialProperties)) {
         $semdata->addPropertyObjectValue(new SMWDIProperty('_NEWP'), new SMWDIBoolean(is_null($rev->getParentId())));
     }
     return true;
 }
Пример #2
0
 /**
  * @return bool
  */
 protected function showHeader()
 {
     global $wgOut, $wgUser, $wgMaxArticleSize, $wgLang;
     global $wgAllowUserCss, $wgAllowUserJs;
     if ($this->mTitle->isTalkPage()) {
         $wgOut->addWikiMsg('talkpagetext');
     }
     // Add edit notices
     $editNotices = $this->mTitle->getEditNotices($this->oldid);
     if (count($editNotices)) {
         $wgOut->addHTML(implode("\n", $editNotices));
     } else {
         $msg = wfMessage('editnotice-notext');
         if (!$msg->isDisabled()) {
             $wgOut->addHTML('<div class="mw-editnotice-notext">' . $msg->parseAsBlock() . '</div>');
         }
     }
     if ($this->isConflict) {
         $wgOut->wrapWikiMsg("<div class='mw-explainconflict'>\n\$1\n</div>", 'explainconflict');
         $this->edittime = $this->page->getTimestamp();
     } else {
         if ($this->section != '' && !$this->isSectionEditSupported()) {
             // We use $this->section to much before this and getVal('wgSection') directly in other places
             // at this point we can't reset $this->section to '' to fallback to non-section editing.
             // Someone is welcome to try refactoring though
             $wgOut->showErrorPage('sectioneditnotsupported-title', 'sectioneditnotsupported-text');
             return false;
         }
         if ($this->section != '' && $this->section != 'new') {
             if (!$this->summary && !$this->preview && !$this->diff) {
                 $sectionTitle = self::extractSectionTitle($this->textbox1);
                 // FIXME: use Content object
                 if ($sectionTitle !== false) {
                     $this->summary = "/* {$sectionTitle} */ ";
                 }
             }
         }
         if ($this->missingComment) {
             $wgOut->wrapWikiMsg("<div id='mw-missingcommenttext'>\n\$1\n</div>", 'missingcommenttext');
         }
         if ($this->missingSummary && $this->section != 'new') {
             $wgOut->wrapWikiMsg("<div id='mw-missingsummary'>\n\$1\n</div>", 'missingsummary');
         }
         if ($this->missingSummary && $this->section == 'new') {
             $wgOut->wrapWikiMsg("<div id='mw-missingcommentheader'>\n\$1\n</div>", 'missingcommentheader');
         }
         if ($this->blankArticle) {
             $wgOut->wrapWikiMsg("<div id='mw-blankarticle'>\n\$1\n</div>", 'blankarticle');
         }
         if ($this->selfRedirect) {
             $wgOut->wrapWikiMsg("<div id='mw-selfredirect'>\n\$1\n</div>", 'selfredirect');
         }
         if ($this->hookError !== '') {
             $wgOut->addWikiText($this->hookError);
         }
         if (!$this->checkUnicodeCompliantBrowser()) {
             $wgOut->addWikiMsg('nonunicodebrowser');
         }
         if ($this->section != 'new') {
             $revision = $this->mArticle->getRevisionFetched();
             if ($revision) {
                 // Let sysop know that this will make private content public if saved
                 if (!$revision->userCan(Revision::DELETED_TEXT, $wgUser)) {
                     $wgOut->wrapWikiMsg("<div class='mw-warning plainlinks'>\n\$1\n</div>\n", 'rev-deleted-text-permission');
                 } elseif ($revision->isDeleted(Revision::DELETED_TEXT)) {
                     $wgOut->wrapWikiMsg("<div class='mw-warning plainlinks'>\n\$1\n</div>\n", 'rev-deleted-text-view');
                 }
                 if (!$revision->isCurrent()) {
                     $this->mArticle->setOldSubtitle($revision->getId());
                     $wgOut->addWikiMsg('editingold');
                 }
             } elseif ($this->mTitle->exists()) {
                 // Something went wrong
                 $wgOut->wrapWikiMsg("<div class='errorbox'>\n\$1\n</div>\n", array('missing-revision', $this->oldid));
             }
         }
     }
     if (wfReadOnly()) {
         $wgOut->wrapWikiMsg("<div id=\"mw-read-only-warning\">\n\$1\n</div>", array('readonlywarning', wfReadOnlyReason()));
     } elseif ($wgUser->isAnon()) {
         if ($this->formtype != 'preview') {
             $wgOut->wrapWikiMsg("<div id='mw-anon-edit-warning'>\n\$1\n</div>", array('anoneditwarning', '{{fullurl:Special:UserLogin|returnto={{FULLPAGENAMEE}}}}', '{{fullurl:Special:UserLogin/signup|returnto={{FULLPAGENAMEE}}}}'));
         } else {
             $wgOut->wrapWikiMsg("<div id=\"mw-anon-preview-warning\">\n\$1</div>", 'anonpreviewwarning');
         }
     } else {
         if ($this->isCssJsSubpage) {
             # Check the skin exists
             if ($this->isWrongCaseCssJsPage) {
                 $wgOut->wrapWikiMsg("<div class='error' id='mw-userinvalidcssjstitle'>\n\$1\n</div>", array('userinvalidcssjstitle', $this->mTitle->getSkinFromCssJsSubpage()));
             }
             if ($this->getTitle()->isSubpageOf($wgUser->getUserPage())) {
                 if ($this->formtype !== 'preview') {
                     if ($this->isCssSubpage && $wgAllowUserCss) {
                         $wgOut->wrapWikiMsg("<div id='mw-usercssyoucanpreview'>\n\$1\n</div>", array('usercssyoucanpreview'));
                     }
                     if ($this->isJsSubpage && $wgAllowUserJs) {
                         $wgOut->wrapWikiMsg("<div id='mw-userjsyoucanpreview'>\n\$1\n</div>", array('userjsyoucanpreview'));
                     }
                 }
             }
         }
     }
     if ($this->mTitle->isProtected('edit') && MWNamespace::getRestrictionLevels($this->mTitle->getNamespace()) !== array('')) {
         # Is the title semi-protected?
         if ($this->mTitle->isSemiProtected()) {
             $noticeMsg = 'semiprotectedpagewarning';
         } else {
             # Then it must be protected based on static groups (regular)
             $noticeMsg = 'protectedpagewarning';
         }
         LogEventsList::showLogExtract($wgOut, 'protect', $this->mTitle, '', array('lim' => 1, 'msgKey' => array($noticeMsg)));
     }
     if ($this->mTitle->isCascadeProtected()) {
         # Is this page under cascading protection from some source pages?
         /** @var Title[] $cascadeSources */
         list($cascadeSources, ) = $this->mTitle->getCascadeProtectionSources();
         $notice = "<div class='mw-cascadeprotectedwarning'>\n\$1\n";
         $cascadeSourcesCount = count($cascadeSources);
         if ($cascadeSourcesCount > 0) {
             # Explain, and list the titles responsible
             foreach ($cascadeSources as $page) {
                 $notice .= '* [[:' . $page->getPrefixedText() . "]]\n";
             }
         }
         $notice .= '</div>';
         $wgOut->wrapWikiMsg($notice, array('cascadeprotectedwarning', $cascadeSourcesCount));
     }
     if (!$this->mTitle->exists() && $this->mTitle->getRestrictions('create')) {
         LogEventsList::showLogExtract($wgOut, 'protect', $this->mTitle, '', array('lim' => 1, 'showIfEmpty' => false, 'msgKey' => array('titleprotectedwarning'), 'wrap' => "<div class=\"mw-titleprotectedwarning\">\n\$1</div>"));
     }
     if ($this->kblength === false) {
         $this->kblength = (int) (strlen($this->textbox1) / 1024);
     }
     if ($this->tooBig || $this->kblength > $wgMaxArticleSize) {
         $wgOut->wrapWikiMsg("<div class='error' id='mw-edit-longpageerror'>\n\$1\n</div>", array('longpageerror', $wgLang->formatNum($this->kblength), $wgLang->formatNum($wgMaxArticleSize)));
     } else {
         if (!wfMessage('longpage-hint')->isDisabled()) {
             $wgOut->wrapWikiMsg("<div id='mw-edit-longpage-hint'>\n\$1\n</div>", array('longpage-hint', $wgLang->formatSize(strlen($this->textbox1)), strlen($this->textbox1)));
         }
     }
     # Add header copyright warning
     $this->showHeaderCopyrightWarning();
     return true;
 }
Пример #3
0
 /**
  * doSaveAsArticle store comment as article
  *
  * @static
  *
  * @param String $text
  * @param Article|WikiPage $article
  * @param User $user
  * @param array $metadata
  * @param string $summary
  *
  * @return Status TODO: Document
  */
 protected static function doSaveAsArticle($text, $article, $user, $metadata = array(), $summary = '')
 {
     $result = null;
     $editPage = new EditPage($article);
     $editPage->edittime = $article->getTimestamp();
     $editPage->textbox1 = self::removeMetadataTag($text);
     $editPage->summary = $summary;
     $editPage->watchthis = $user->isWatched($article->getTitle());
     if (!empty($metadata)) {
         $editPage->textbox1 = $text . Xml::element('ac_metadata', $metadata, ' ');
     }
     $bot = $user->isAllowed('bot');
     return $editPage->internalAttemptSave($result, $bot);
 }
Пример #4
0
 /**
  * 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', [$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', [$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
         if (!wfReadOnly()) {
             $wgUser->spreadAnyEditBlock();
         }
         # Check block state against master, thus 'false'.
         $status->setResult(false, self::AS_BLOCKED_PAGE_FOR_USER);
         return $status;
     }
     $this->contentLength = strlen($this->textbox1);
     if ($this->contentLength > $wgMaxArticleSize * 1024) {
         // 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;
         }
         // Make sure the user can edit the page under the new content model too
         $titleWithNewContentModel = clone $this->mTitle;
         $titleWithNewContentModel->setContentModel($this->contentModel);
         if (!$titleWithNewContentModel->userCan('editcontentmodel', $wgUser) || !$titleWithNewContentModel->userCan('edit', $wgUser)) {
             $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) || $changingContentModel && $wgUser->pingLimiter('editcontentmodel')) {
         $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();
         $latest = $this->page->getLatest();
         wfDebug("timestamp: {$timestamp}, edittime: {$this->edittime}\n");
         // Check editRevId if set, which handles same-second timestamp collisions
         if ($timestamp != $this->edittime || $this->editRevId !== null && $this->editRevId != $latest) {
             $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}'" . " (id '{$this->editRevId}') (article time '{$timestamp}')\n");
             // @TODO: replaceSectionAtRev() with base ID (not prior current) for ?oldid=X case
             // ...or disable section editing for non-current revisions (not exposed anyway).
             if ($this->editRevId !== null) {
                 $content = $this->page->replaceSectionAtRev($this->section, $textbox_content, $sectionTitle, $this->editRevId);
             } else {
                 $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::replaceSectionAtRev
             # 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->contentLength = strlen($this->toEditText($content));
     if ($this->contentLength > $wgMaxArticleSize * 1024) {
         $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], ['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, $new ? false : $oldContentModel, $this->contentModel, $this->summary);
     }
     return $status;
 }
Пример #5
0
 /**
  * Fetch additional information that is related to the saving that has just happened,
  * e.g. regarding the last edit date. In runs where this hook is not triggered, the
  * last DB entry (of MW) will be used to fill such properties.
  *
  * @note This method directly accesses a member of Article that is informally declared to
  * be private. However, there is no way to otherwise access an article's parseroutput for
  * the purpose of adding information there. If the private access ever becomes a problem,
  * a global/static variable appears to be the only way to get more article data to
  * LinksUpdate.
  *
  * @param WikiPage|Article $article WikiPage on 1.19 and later
  * @param Revision $rev
  * @param integer $baseID
  * @param User $user
  *
  * @return true
  */
 public static function onNewRevisionFromEditComplete($article, Revision $rev, $baseID, User $user)
 {
     global $smwgPageSpecialProperties;
     if ($article->mPreparedEdit && $article->mPreparedEdit->output instanceof ParserOutput) {
         $semdata = self::getSMWDataFromParserOutput($article->mPreparedEdit->output, $article->getTitle());
     } else {
         // give up, just keep the old data
         return true;
     }
     if (in_array('_MDAT', $smwgPageSpecialProperties)) {
         $timestamp = $article->getTimestamp();
         $di = self::getDataItemFromMWTimestamp($timestamp);
         if (!is_null($di)) {
             $semdata->addPropertyObjectValue(new SMWDIProperty('_MDAT'), $di);
         }
     }
     if (in_array('_LEDT', $smwgPageSpecialProperties)) {
         $di = SMWDIWikiPage::newFromTitle($user->getUserPage());
         if (!is_null($di)) {
             $semdata->addPropertyObjectValue(new SMWDIProperty('_LEDT'), $di);
         }
     }
     if (in_array('_NEWP', $smwgPageSpecialProperties)) {
         $semdata->addPropertyObjectValue(new SMWDIProperty('_NEWP'), new SMWDIBoolean(is_null($rev->getParentId())));
     }
     return true;
 }