editpage.php
来自「php 开发的内容管理系统」· PHP 代码 · 共 1,865 行 · 第 1/4 页
PHP
1,865 行
<?php/** * Contain the EditPage class * @package MediaWiki *//** * Splitting edit page/HTML interface from Article... * The actual database and text munging is still in Article, * but it should get easier to call those from alternate * interfaces. * * @package MediaWiki */class EditPage { var $mArticle; var $mTitle; var $mMetaData = ''; var $isConflict = false; var $isCssJsSubpage = false; var $deletedSinceEdit = false; var $formtype; var $firsttime; var $lastDelete; var $mTokenOk = false; var $mTriedSave = false; var $tooBig = false; var $kblength = false; var $missingComment = false; var $missingSummary = false; var $allowBlankSummary = false; var $autoSumm = ''; var $hookError = ''; # Form values var $save = false, $preview = false, $diff = false; var $minoredit = false, $watchthis = false, $recreate = false; var $textbox1 = '', $textbox2 = '', $summary = ''; var $edittime = '', $section = '', $starttime = ''; var $oldid = 0, $editintro = '', $scrolltop = null; /** * @todo document * @param $article */ function EditPage( $article ) { $this->mArticle =& $article; global $wgTitle; $this->mTitle =& $wgTitle; } /** * Fetch initial editing page content. */ private function getContent() { global $wgRequest, $wgParser; # Get variables from query string :P $section = $wgRequest->getVal( 'section' ); $preload = $wgRequest->getVal( 'preload' ); wfProfileIn( __METHOD__ ); $text = ''; if( !$this->mTitle->exists() ) { # If requested, preload some text. $text = $this->getPreloadedText( $preload ); # We used to put MediaWiki:Newarticletext here if # $text was empty at this point. # This is now shown above the edit box instead. } else { // FIXME: may be better to use Revision class directly // But don't mess with it just yet. Article knows how to // fetch the page record from the high-priority server, // which is needed to guarantee we don't pick up lagged // information. $text = $this->mArticle->getContent(); if( $section != '' ) { if( $section == 'new' ) { $text = $this->getPreloadedText( $preload ); } else { $text = $wgParser->getSection( $text, $section ); } } } wfProfileOut( __METHOD__ ); return $text; } /** * Get the contents of a page from its title and remove includeonly tags * * @param $preload String: the title of the page. * @return string The contents of the page. */ private function getPreloadedText($preload) { if ( $preload === '' ) return ''; else { $preloadTitle = Title::newFromText( $preload ); if ( isset( $preloadTitle ) && $preloadTitle->userCanRead() ) { $rev=Revision::newFromTitle($preloadTitle); if ( is_object( $rev ) ) { $text = $rev->getText(); // TODO FIXME: AAAAAAAAAAA, this shouldn't be implementing // its own mini-parser! -忙var $text = preg_replace( '~</?includeonly>~', '', $text ); return $text; } else return ''; } } } /** * This is the function that extracts metadata from the article body on the first view. * To turn the feature on, set $wgUseMetadataEdit = true ; in LocalSettings * and set $wgMetadataWhitelist to the *full* title of the template whitelist */ function extractMetaDataFromArticle () { global $wgUseMetadataEdit , $wgMetadataWhitelist , $wgLang ; $this->mMetaData = '' ; if ( !$wgUseMetadataEdit ) return ; if ( $wgMetadataWhitelist == '' ) return ; $s = '' ; $t = $this->getContent(); # MISSING : <nowiki> filtering # Categories and language links $t = explode ( "\n" , $t ) ; $catlow = strtolower ( $wgLang->getNsText ( NS_CATEGORY ) ) ; $cat = $ll = array() ; foreach ( $t AS $key => $x ) { $y = trim ( strtolower ( $x ) ) ; while ( substr ( $y , 0 , 2 ) == '[[' ) { $y = explode ( ']]' , trim ( $x ) ) ; $first = array_shift ( $y ) ; $first = explode ( ':' , $first ) ; $ns = array_shift ( $first ) ; $ns = trim ( str_replace ( '[' , '' , $ns ) ) ; if ( strlen ( $ns ) == 2 OR strtolower ( $ns ) == $catlow ) { $add = '[[' . $ns . ':' . implode ( ':' , $first ) . ']]' ; if ( strtolower ( $ns ) == $catlow ) $cat[] = $add ; else $ll[] = $add ; $x = implode ( ']]' , $y ) ; $t[$key] = $x ; $y = trim ( strtolower ( $x ) ) ; } } } if ( count ( $cat ) ) $s .= implode ( ' ' , $cat ) . "\n" ; if ( count ( $ll ) ) $s .= implode ( ' ' , $ll ) . "\n" ; $t = implode ( "\n" , $t ) ; # Load whitelist $sat = array () ; # stand-alone-templates; must be lowercase $wl_title = Title::newFromText ( $wgMetadataWhitelist ) ; $wl_article = new Article ( $wl_title ) ; $wl = explode ( "\n" , $wl_article->getContent() ) ; foreach ( $wl AS $x ) { $isentry = false ; $x = trim ( $x ) ; while ( substr ( $x , 0 , 1 ) == '*' ) { $isentry = true ; $x = trim ( substr ( $x , 1 ) ) ; } if ( $isentry ) { $sat[] = strtolower ( $x ) ; } } # Templates, but only some $t = explode ( '{{' , $t ) ; $tl = array () ; foreach ( $t AS $key => $x ) { $y = explode ( '}}' , $x , 2 ) ; if ( count ( $y ) == 2 ) { $z = $y[0] ; $z = explode ( '|' , $z ) ; $tn = array_shift ( $z ) ; if ( in_array ( strtolower ( $tn ) , $sat ) ) { $tl[] = '{{' . $y[0] . '}}' ; $t[$key] = $y[1] ; $y = explode ( '}}' , $y[1] , 2 ) ; } else $t[$key] = '{{' . $x ; } else if ( $key != 0 ) $t[$key] = '{{' . $x ; else $t[$key] = $x ; } if ( count ( $tl ) ) $s .= implode ( ' ' , $tl ) ; $t = implode ( '' , $t ) ; $t = str_replace ( "\n\n\n" , "\n" , $t ) ; $this->mArticle->mContent = $t ; $this->mMetaData = $s ; } function submit() { $this->edit(); } /** * This is the function that gets called for "action=edit". It * sets up various member variables, then passes execution to * another function, usually showEditForm() * * The edit form is self-submitting, so that when things like * preview and edit conflicts occur, we get the same form back * with the extra stuff added. Only when the final submission * is made and all is well do we actually save and redirect to * the newly-edited page. */ function edit() { global $wgOut, $wgUser, $wgRequest, $wgTitle; global $wgEmailConfirmToEdit; if ( ! wfRunHooks( 'AlternateEdit', array( &$this ) ) ) return; $fname = 'EditPage::edit'; wfProfileIn( $fname ); wfDebug( "$fname: enter\n" ); // this is not an article $wgOut->setArticleFlag(false); $this->importFormData( $wgRequest ); $this->firsttime = false; if( $this->live ) { $this->livePreview(); wfProfileOut( $fname ); return; } if ( ! $this->mTitle->userCanEdit() ) { wfDebug( "$fname: user can't edit\n" ); $wgOut->readOnlyPage( $this->getContent(), true ); wfProfileOut( $fname ); return; } wfDebug( "$fname: Checking blocks\n" ); if ( !$this->preview && !$this->diff && $wgUser->isBlockedFrom( $this->mTitle, !$this->save ) ) { # When previewing, don't check blocked state - will get caught at save time. # Also, check when starting edition is done against slave to improve performance. wfDebug( "$fname: user is blocked\n" ); $this->blockedPage(); wfProfileOut( $fname ); return; } if ( !$wgUser->isAllowed('edit') ) { if ( $wgUser->isAnon() ) { wfDebug( "$fname: user must log in\n" ); $this->userNotLoggedInPage(); wfProfileOut( $fname ); return; } else { wfDebug( "$fname: read-only page\n" ); $wgOut->readOnlyPage( $this->getContent(), true ); wfProfileOut( $fname ); return; } } if ($wgEmailConfirmToEdit && !$wgUser->isEmailConfirmed()) { wfDebug("$fname: user must confirm e-mail address\n"); $this->userNotConfirmedPage(); wfProfileOut($fname); return; } if ( !$this->mTitle->userCanCreate() && !$this->mTitle->exists() ) { wfDebug( "$fname: no create permission\n" ); $this->noCreatePermission(); wfProfileOut( $fname ); return; } if ( wfReadOnly() ) { wfDebug( "$fname: read-only mode is engaged\n" ); if( $this->save || $this->preview ) { $this->formtype = 'preview'; } else if ( $this->diff ) { $this->formtype = 'diff'; } else { $wgOut->readOnlyPage( $this->getContent() ); wfProfileOut( $fname ); return; } } else { if ( $this->save ) { $this->formtype = 'save'; } else if ( $this->preview ) { $this->formtype = 'preview'; } else if ( $this->diff ) { $this->formtype = 'diff'; } else { # First time through $this->firsttime = true; if( $this->previewOnOpen() ) { $this->formtype = 'preview'; } else { $this->extractMetaDataFromArticle () ; $this->formtype = 'initial'; } } } wfProfileIn( "$fname-business-end" ); $this->isConflict = false; // css / js subpages of user pages get a special treatment $this->isCssJsSubpage = $wgTitle->isCssJsSubpage(); $this->isValidCssJsSubpage = $wgTitle->isValidCssJsSubpage(); /* Notice that we can't use isDeleted, because it returns true if article is ever deleted * no matter it's current state */ $this->deletedSinceEdit = false; if ( $this->edittime != '' ) { /* Note that we rely on logging table, which hasn't been always there, * but that doesn't matter, because this only applies to brand new * deletes. This is done on every preview and save request. Move it further down * to only perform it on saves */ if ( $this->mTitle->isDeleted() ) { $this->lastDelete = $this->getLastDelete(); if ( !is_null($this->lastDelete) ) { $deletetime = $this->lastDelete->log_timestamp; if ( ($deletetime - $this->starttime) > 0 ) { $this->deletedSinceEdit = true; } } } } if(!$this->mTitle->getArticleID() && ('initial' == $this->formtype || $this->firsttime )) { # new article $this->showIntro(); } if( $this->mTitle->isTalkPage() ) { $wgOut->addWikiText( wfMsg( 'talkpagetext' ) ); } # Attempt submission here. This will check for edit conflicts, # and redundantly check for locked database, blocked IPs, etc. # that edit() already checked just in case someone tries to sneak # in the back door with a hand-edited submission URL. if ( 'save' == $this->formtype ) { if ( !$this->attemptSave() ) { wfProfileOut( "$fname-business-end" ); wfProfileOut( $fname ); return; } } # First time through: get contents, set time for conflict # checking, etc. if ( 'initial' == $this->formtype || $this->firsttime ) { $this->initialiseForm(); if( !$this->mTitle->getArticleId() ) wfRunHooks( 'EditFormPreloadText', array( &$this->textbox1, &$this->mTitle ) ); } $this->showEditForm(); wfProfileOut( "$fname-business-end" ); wfProfileOut( $fname ); } /** * Return true if this page should be previewed when the edit form * is initially opened. * @return bool * @private */ function previewOnOpen() { global $wgUser; return $this->section != 'new' && ( ( $wgUser->getOption( 'previewonfirst' ) && $this->mTitle->exists() ) || ( $this->mTitle->getNamespace() == NS_CATEGORY && !$this->mTitle->exists() ) ); } /** * @todo document * @param $request */ function importFormData( &$request ) { global $wgLang, $wgUser; $fname = 'EditPage::importFormData'; wfProfileIn( $fname ); if( $request->wasPosted() ) { # These fields need to be checked for encoding. # Also remove trailing whitespace, but don't remove _initial_ # whitespace from the text boxes. This may be significant formatting. $this->textbox1 = $this->safeUnicodeInput( $request, 'wpTextbox1' ); $this->textbox2 = $this->safeUnicodeInput( $request, 'wpTextbox2' ); $this->mMetaData = rtrim( $request->getText( 'metadata' ) ); # Truncate for whole multibyte characters. +5 bytes for ellipsis $this->summary = $wgLang->truncate( $request->getText( 'wpSummary' ), 250 ); $this->edittime = $request->getVal( 'wpEdittime' ); $this->starttime = $request->getVal( 'wpStarttime' ); $this->scrolltop = $request->getIntOrNull( 'wpScrolltop' ); if( is_null( $this->edittime ) ) { # If the form is incomplete, force to preview. wfDebug( "$fname: Form data appears to be incomplete\n" ); wfDebug( "POST DATA: " . var_export( $_POST, true ) . "\n" ); $this->preview = true; } else { /* Fallback for live preview */ $this->preview = $request->getCheck( 'wpPreview' ) || $request->getCheck( 'wpLivePreview' ); $this->diff = $request->getCheck( 'wpDiff' ); // Remember whether a save was requested, so we can indicate // if we forced preview due to session failure. $this->mTriedSave = !$this->preview; if ( $this->tokenOk( $request ) ) { # Some browsers will not report any submit button # if the user hits enter in the comment box. # The unmarked state will be assumed to be a save, # if the form seems otherwise complete. wfDebug( "$fname: Passed token check.\n" ); } else { # Page might be a hack attempt posted from # an external site. Preview instead of saving. wfDebug( "$fname: Failed token check; forcing preview\n" ); $this->preview = true; } } $this->save = ! ( $this->preview OR $this->diff ); if( !preg_match( '/^\d{14}$/', $this->edittime )) { $this->edittime = null; } if( !preg_match( '/^\d{14}$/', $this->starttime )) { $this->starttime = null; } $this->recreate = $request->getCheck( 'wpRecreate' ); $this->minoredit = $request->getCheck( 'wpMinoredit' ); $this->watchthis = $request->getCheck( 'wpWatchthis' ); # Don't force edit summaries when a user is editing their own user or talk page if( ( $this->mTitle->mNamespace == NS_USER || $this->mTitle->mNamespace == NS_USER_TALK ) && $this->mTitle->getText() == $wgUser->getName() ) { $this->allowBlankSummary = true; } else { $this->allowBlankSummary = $request->getBool( 'wpIgnoreBlankSummary' );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?