* usually the same, but they are now allowed to be different.
*/
class EditPage {
- const AS_SUCCESS_UPDATE = 200;
- const AS_SUCCESS_NEW_ARTICLE = 201;
- const AS_HOOK_ERROR = 210;
- const AS_FILTERING = 211;
- const AS_HOOK_ERROR_EXPECTED = 212;
- const AS_BLOCKED_PAGE_FOR_USER = 215;
- const AS_CONTENT_TOO_BIG = 216;
- const AS_USER_CANNOT_EDIT = 217;
- const AS_READ_ONLY_PAGE_ANON = 218;
- const AS_READ_ONLY_PAGE_LOGGED = 219;
- const AS_READ_ONLY_PAGE = 220;
- const AS_RATE_LIMITED = 221;
- const AS_ARTICLE_WAS_DELETED = 222;
- const AS_NO_CREATE_PERMISSION = 223;
- const AS_BLANK_ARTICLE = 224;
- const AS_CONFLICT_DETECTED = 225;
- const AS_SUMMARY_NEEDED = 226;
- const AS_TEXTBOX_EMPTY = 228;
- const AS_MAX_ARTICLE_SIZE_EXCEEDED = 229;
- const AS_OK = 230;
- const AS_END = 231;
- const AS_SPAM_ERROR = 232;
- const AS_IMAGE_REDIRECT_ANON = 233;
- const AS_IMAGE_REDIRECT_LOGGED = 234;
+ const AS_SUCCESS_UPDATE = 200;
+ const AS_SUCCESS_NEW_ARTICLE = 201;
+ const AS_HOOK_ERROR = 210;
+ const AS_FILTERING = 211;
+ const AS_HOOK_ERROR_EXPECTED = 212;
+ const AS_BLOCKED_PAGE_FOR_USER = 215;
+ const AS_CONTENT_TOO_BIG = 216;
+ const AS_USER_CANNOT_EDIT = 217;
+ const AS_READ_ONLY_PAGE_ANON = 218;
+ const AS_READ_ONLY_PAGE_LOGGED = 219;
+ const AS_READ_ONLY_PAGE = 220;
+ const AS_RATE_LIMITED = 221;
+ const AS_ARTICLE_WAS_DELETED = 222;
+ const AS_NO_CREATE_PERMISSION = 223;
+ const AS_BLANK_ARTICLE = 224;
+ const AS_CONFLICT_DETECTED = 225;
+ const AS_SUMMARY_NEEDED = 226;
+ const AS_TEXTBOX_EMPTY = 228;
+ const AS_MAX_ARTICLE_SIZE_EXCEEDED = 229;
+ const AS_OK = 230;
+ const AS_END = 231;
+ const AS_SPAM_ERROR = 232;
+ const AS_IMAGE_REDIRECT_ANON = 233;
+ const AS_IMAGE_REDIRECT_LOGGED = 234;
var $mArticle;
var $mTitle;
# Form values
var $save = false, $preview = false, $diff = false;
var $minoredit = false, $watchthis = false, $recreate = false;
- var $textbox1 = '', $textbox2 = '', $summary = '';
+ var $textbox1 = '', $textbox2 = '', $summary = '', $nosummary = false;
var $edittime = '', $section = '', $starttime = '';
- var $oldid = 0, $editintro = '', $scrolltop = null;
+ var $oldid = 0, $editintro = '', $scrolltop = null, $bot = true;
# Placeholders for text injection by hooks (must be HTML)
# extensions should take care to _append_ to the present value
/**
* Fetch initial editing page content.
+ * @returns mixed string on success, $def_text for invalid sections
* @private
*/
function getContent( $def_text = '' ) {
wfProfileIn( __METHOD__ );
# Get variables from query string :P
$section = $wgRequest->getVal( 'section' );
- $preload = $wgRequest->getVal( 'preload' );
+
+ $preload = $wgRequest->getVal( 'preload',
+ // Custom preload text for new sections
+ $section === 'new' ? 'MediaWiki:addsection-preload' : '' );
$undoafter = $wgRequest->getVal( 'undoafter' );
$undo = $wgRequest->getVal( 'undo' );
if ( $section == 'new' ) {
$text = $this->getPreloadedText( $preload );
} else {
+ // Get section edit text (returns $def_text for invalid sections)
$text = $wgParser->getSection( $text, $section, $def_text );
}
}
$permErrors = $this->getEditPermissionErrors();
if ( $permErrors ) {
wfDebug( __METHOD__ . ": User can't edit\n" );
- $this->readOnlyPage( $this->getContent(), true, $permErrors, 'edit' );
+ $this->readOnlyPage( $this->getContent( false ), true, $permErrors, 'edit' );
wfProfileOut( __METHOD__ );
return;
} else {
* @return bool
*/
protected function previewOnOpen() {
- global $wgRequest, $wgUser;
+ global $wgRequest, $wgUser, $wgPreviewOnOpenNamespaces;
if ( $wgRequest->getVal( 'preview' ) == 'yes' ) {
// Explicit override from request
return true;
} elseif ( ( $wgRequest->getVal( 'preload' ) !== null || $this->mTitle->exists() ) && $wgUser->getOption( 'previewonfirst' ) ) {
// Standard preference behaviour
return true;
- } elseif ( !$this->mTitle->exists() && $this->mTitle->getNamespace() == NS_CATEGORY ) {
+ } elseif ( !$this->mTitle->exists() &&
+ isset($wgPreviewOnOpenNamespaces[$this->mTitle->getNamespace()]) &&
+ $wgPreviewOnOpenNamespaces[$this->mTitle->getNamespace()] )
+ {
// Categories are special
return true;
} else {
$this->save = false;
$this->diff = false;
$this->minoredit = false;
- $this->watchthis = false;
+ $this->watchthis = $request->getBool( 'watchthis', false ); // Watch may be overriden by request parameters
$this->recreate = false;
if ( $this->section == 'new' && $request->getVal( 'preloadtitle' ) ) {
}
}
+ $this->bot = $request->getBool( 'bot', true );
+ $this->nosummary = $request->getBool( 'nosummary' );
+
// FIXME: unused variable?
$this->oldid = $request->getInt( 'oldid' );
$this->live = $request->getCheck( 'live' );
- $this->editintro = $request->getText( 'editintro' );
+ $this->editintro = $request->getText( 'editintro',
+ // Custom edit intro for new sections
+ $this->section === 'new' ? 'MediaWiki:addsection-editintro' : '' );
wfProfileOut( __METHOD__ );
$id = User::idFromName( $username );
$ip = User::isIP( $username );
if ( $id == 0 && !$ip ) {
- $wgOut->wrapWikiMsg( '<div class="mw-userpage-userdoesnotexist error">$1</div>',
+ $wgOut->wrapWikiMsg( "<div class=\"mw-userpage-userdoesnotexist error\">\n$1</div>",
array( 'userpage-userdoesnotexist', $username ) );
}
}
# Try to add a custom edit intro, or use the standard one if this is not possible.
if ( !$this->showCustomIntro() && !$this->mTitle->exists() ) {
if ( $wgUser->isLoggedIn() ) {
- $wgOut->wrapWikiMsg( '<div class="mw-newarticletext">$1</div>', 'newarticletext' );
+ $wgOut->wrapWikiMsg( "<div class=\"mw-newarticletext\">\n$1</div>", 'newarticletext' );
} else {
- $wgOut->wrapWikiMsg( '<div class="mw-newarticletextanon">$1</div>', 'newarticletextanon' );
+ $wgOut->wrapWikiMsg( "<div class=\"mw-newarticletextanon\">\n$1</div>", 'newarticletextanon' );
}
}
# Give a notice if the user is editing a deleted/moved page...
}
# Don't save a new article if it's blank.
- if ( '' == $this->textbox1 ) {
+ if ( $this->textbox1 == '' ) {
wfProfileOut( __METHOD__ );
return self::AS_BLANK_ARTICLE;
}
/**
* Initialise form fields in the object
* Called on the first invocation, e.g. when a user clicks an edit link
+ * @returns bool -- if the requested section is valid
*/
function initialiseForm() {
+ global $wgUser;
$this->edittime = $this->mArticle->getTimestamp();
$this->textbox1 = $this->getContent( false );
+ // activate checkboxes if user wants them to be always active
+ # Sort out the "watch" checkbox
+ if ( $wgUser->getOption( 'watchdefault' ) ) {
+ # Watch all edits
+ $this->watchthis = true;
+ } elseif ( $wgUser->getOption( 'watchcreations' ) && !$this->mTitle->exists() ) {
+ # Watch creations
+ $this->watchthis = true;
+ } elseif ( $this->mTitle->userIsWatching() ) {
+ # Already watched
+ $this->watchthis = true;
+ }
+ if ( $wgUser->getOption( 'minordefault' ) ) $this->minoredit = true;
if ( $this->textbox1 === false ) return false;
wfProxyCheck();
return true;
* near the top, for captchas and the like.
*/
function showEditForm( $formCallback=null ) {
- global $wgOut, $wgUser, $wgTitle, $wgRequest;
+ global $wgOut, $wgUser, $wgTitle;
# If $wgTitle is null, that means we're in API mode.
# Some hook probably called this function without checking
# Enabled article-related sidebar, toplinks, etc.
$wgOut->setArticleRelated( true );
- if ( $this->editFormHeadInit() === false )
+ if ( $this->showHeader() === false )
return;
$action = htmlspecialchars($this->getActionURL($wgTitle));
}
- // activate checkboxes if user wants them to be always active
- if ( !$this->preview && !$this->diff ) {
- # Sort out the "watch" checkbox
- if ( $wgUser->getOption( 'watchdefault' ) ) {
- # Watch all edits
- $this->watchthis = true;
- } elseif ( $wgUser->getOption( 'watchcreations' ) && !$this->mTitle->exists() ) {
- # Watch creations
- $this->watchthis = true;
- } elseif ( $this->mTitle->userIsWatching() ) {
- # Already watched
- $this->watchthis = true;
- }
-
- # May be overriden by request parameters
- if( $wgRequest->getBool( 'watchthis' ) ) {
- $this->watchthis = true;
- }
-
- if ( $wgUser->getOption( 'minordefault' ) ) $this->minoredit = true;
- }
-
$wgOut->addHTML( $this->editFormPageTop );
if ( $wgUser->getOption( 'previewontop' ) ) {
$toolbar = '';
// @todo move this to a cleaner conditional instead of blanking a variable
}
- $wgOut->addHTML( <<<END
+ $wgOut->addHTML( <<<HTML
{$toolbar}
<form id="editform" name="editform" method="post" action="$action" enctype="multipart/form-data">
-END
+HTML
);
if ( is_callable( $formCallback ) ) {
# For a bit more sophisticated detection of blank summaries, hash the
# automatic one and pass that in the hidden field wpAutoSummary.
if ( $this->missingSummary ||
- ( $this->section == 'new' && $wgRequest->getBool( 'nosummary' ) ) )
+ ( $this->section == 'new' && $this->nosummary ) )
$wgOut->addHTML( Xml::hidden( 'wpIgnoreBlankSummary', true ) );
$autosumm = $this->autoSumm ? $this->autoSumm : md5( $this->summary );
$wgOut->addHTML( Xml::hidden( 'wpAutoSummary', $autosumm ) );
$this->showTosSummary();
$this->showEditTools();
- $wgOut->addHTML( <<<END
+ $wgOut->addHTML( <<<HTML
{$this->editFormTextAfterTools}
<div class='templatesUsed'>
{$formattedtemplates}
<div class='hiddencats'>
{$formattedhiddencats}
</div>
-END
+HTML
);
if ( $this->isConflict )
wfProfileOut( __METHOD__ );
}
- protected function editFormHeadInit() {
- global $wgOut, $wgParser, $wgUser, $wgMaxArticleSize, $wgLang;
+ protected function showHeader() {
+ global $wgOut, $wgUser, $wgTitle, $wgMaxArticleSize, $wgLang;
if ( $this->isConflict ) {
$wgOut->wrapWikiMsg( "<div class='mw-explainconflict'>\n$1</div>", 'explainconflict' );
$this->edittime = $this->mArticle->getTimestamp();
}
}
- if ( $this->missingComment )
- $wgOut->wrapWikiMsg( '<div id="mw-missingcommenttext">$1</div>', 'missingcommenttext' );
+ if ( $this->missingComment ) {
+ $wgOut->wrapWikiMsg( "<div id='mw-missingcommenttext'>\n$1</div>", 'missingcommenttext' );
+ }
- if ( $this->missingSummary && $this->section != 'new' )
- $wgOut->wrapWikiMsg( '<div id="mw-missingsummary">$1</div>', 'missingsummary' );
+ if ( $this->missingSummary && $this->section != 'new' ) {
+ $wgOut->wrapWikiMsg( "<div id='mw-missingsummary'>\n$1</div>", 'missingsummary' );
+ }
- if ( $this->missingSummary && $this->section == 'new' )
- $wgOut->wrapWikiMsg( '<div id="mw-missingcommentheader">$1</div>', 'missingcommentheader' );
+ if ( $this->missingSummary && $this->section == 'new' ) {
+ $wgOut->wrapWikiMsg( "<div id='mw-missingcommentheader'>\n$1</div>", 'missingcommentheader' );
+ }
- if ( $this->hookError !== '' )
+ if ( $this->hookError !== '' ) {
$wgOut->addWikiText( $this->hookError );
+ }
- if ( !$this->checkUnicodeCompliantBrowser() )
+ if ( !$this->checkUnicodeCompliantBrowser() ) {
$wgOut->addWikiMsg( 'nonunicodebrowser' );
+ }
if ( isset( $this->mArticle ) && isset( $this->mArticle->mRevision ) ) {
// Let sysop know that this will make private content public if saved
if ( wfReadOnly() ) {
$wgOut->wrapWikiMsg( "<div id=\"mw-read-only-warning\">\n$1\n</div>", array( 'readonlywarning', wfReadOnlyReason() ) );
} elseif ( $wgUser->isAnon() && $this->formtype != 'preview' ) {
- $wgOut->wrapWikiMsg( '<div id="mw-anon-edit-warning">$1</div>', 'anoneditwarning' );
+ $wgOut->wrapWikiMsg( "<div id=\"mw-anon-edit-warning\">\n$1</div>", 'anoneditwarning' );
} else {
if ( $this->isCssJsSubpage ) {
# Check the skin exists
if ( $this->mTitle->isCascadeProtected() ) {
# Is this page under cascading protection from some source pages?
list($cascadeSources, /* $restrictions */) = $this->mTitle->getCascadeProtectionSources();
- $notice = "<div class='mw-cascadeprotectedwarning'>$1\n";
+ $notice = "<div class='mw-cascadeprotectedwarning'>\n$1\n";
$cascadeSourcesCount = count( $cascadeSources );
if ( $cascadeSourcesCount > 0 ) {
# Explain, and list the titles responsible
$wgOut->wrapWikiMsg( $notice, array( 'cascadeprotectedwarning', $cascadeSourcesCount ) );
}
if ( !$this->mTitle->exists() && $this->mTitle->getRestrictions( 'create' ) ) {
- $wgOut->wrapWikiMsg( '<div class="mw-titleprotectedwarning">$1</div>', 'titleprotectedwarning' );
+ LogEventsList::showLogExtract( $wgOut, 'protect', $this->mTitle->getPrefixedText(), '',
+ array( 'lim' => 1,
+ 'showIfEmpty' => false,
+ 'msgKey' => array( 'titleprotectedwarning' ),
+ 'wrap' => "<div class=\"mw-titleprotectedwarning\">\n$1</div>" ) );
}
- if ( $this->kblength === false )
+ if ( $this->kblength === false ) {
$this->kblength = (int)( strlen( $this->textbox1 ) / 1024 );
+ }
if ( $this->tooBig || $this->kblength > $wgMaxArticleSize ) {
$wgOut->addHTML( "<div class='error' id='mw-edit-longpageerror'>\n" );
*
* @return array An array in the format array( $label, $input )
*/
- function getSummaryInput($summary = "", $labelText = null, $userInputAttrs = null, $userSpanLabelAttrs = null) {
- $inputAttrs = array(
+ function getSummaryInput($summary = "", $labelText = null, $inputAttrs = null, $spanLabelAttrs = null) {
+ $inputAttrs = ( is_array($inputAttrs) ? $inputAttrs : array() ) + array(
'id' => 'wpSummary',
'maxlength' => '200',
'tabindex' => '1',
'size' => 60,
'spellcheck' => 'true',
- 'onfocus' => "currentFocused = this;",
);
- if ( $userInputAttrs )
- $inputAttrs += $userInputAttrs;
- $spanLabelAttrs = array(
- 'class' => $summaryClass,
+
+ $spanLabelAttrs = ( is_array($spanLabelAttrs) ? $spanLabelAttrs : array() ) + array(
+ 'class' => $this->missingSummary ? 'mw-summarymissed' : 'mw-summary',
'id' => "wpSummaryLabel"
);
- if ( is_array($userSpanLabelAttrs) )
- $spanLabelAttrs += $userSpanLabelAttrs;
$label = null;
if ( $labelText ) {
# Add a class if 'missingsummary' is triggered to allow styling of the summary line
$summaryClass = $this->missingSummary ? 'mw-summarymissed' : 'mw-summary';
if ( $isSubjectPreview ) {
- if ( $wgRequest->getBool( 'nosummary' ) )
+ if ( $this->nosummary )
return;
} else {
if ( !$this->mShowSummaryField )
$classes[] = $attribs['class'];
$attribs['class'] = implode( ' ', $classes );
}
-
- # Set focus to the edit box on load, except on preview or diff, where it would interfere with the display
- if ( !$this->preview && !$this->diff ) {
- global $wgOut;
- $wgOut->setOnloadHandler( 'document.editform.wpTextbox1.focus();' );
- }
$this->showTextbox( isset($textoverride) ? $textoverride : $this->textbox1, 'wpTextbox1', $attribs );
}
'id' => $name,
'cols' => $wgUser->getIntOption( 'cols' ),
'rows' => $wgUser->getIntOption( 'rows' ),
- 'onfocus' => "currentFocused = this;",
+ 'style' => '' // avoid php notices when appending for editwidth preference (appending allows customAttribs['style'] to still work
);
if ( $wgUser->getOption( 'editwidth' ) )
* Call the stock "user is blocked" page
*/
function blockedPage() {
- global $wgOut, $wgUser;
+ global $wgOut;
$wgOut->blockedPage( false ); # Standard block notice on the top, don't 'return'
# If the user made changes, preserve them when showing the markup
# Spit out the source or the user's modified version
if ( $source !== false ) {
- $rows = $wgUser->getIntOption( 'rows' );
- $cols = $wgUser->getIntOption( 'cols' );
- $attribs = array( 'id' => 'wpTextbox1', 'name' => 'wpTextbox1', 'cols' => $cols, 'rows' => $rows, 'readonly' => 'readonly' );
$wgOut->addHTML( '<hr />' );
$wgOut->addWikiMsg( $first ? 'blockedoriginalsource' : 'blockededitsource', $this->mTitle->getPrefixedText() );
- # Why we don't use Xml::element here?
- # Is it because if $source is '', it returns <textarea />?
- $wgOut->addHTML( Xml::openElement( 'textarea', $attribs ) . htmlspecialchars( $source ) . Xml::closeElement( 'textarea' ) );
+ $this->showTextbox1( array( 'readonly' ), $source );
}
}
* they have attempted to edit a nonexistent section.
*/
function noSuchSectionPage() {
- global $wgOut, $wgTitle;
+ global $wgOut;
$wgOut->setPageTitle( wfMsg( 'nosuchsectiontitle' ) );
$wgOut->setRobotPolicy( 'noindex,nofollow' );
$wgOut->setArticleRelated( false );
- $wgOut->addWikiMsg( 'nosuchsectiontext', $this->section );
- $wgOut->returnToMain( false, $wgTitle );
+ $res = wfMsgExt( 'nosuchsectiontext', 'parse', $this->section );
+ wfRunHooks( 'EditPageNoSuchSection', array( &$this, &$res ) );
+ $wgOut->addHTML( $res );
+
+ $wgOut->returnToMain( false, $this->mTitle );
}
/**
* @return bool false if output is done, true if the rest of the form should be displayed
*/
function attemptSave() {
- global $wgUser, $wgOut, $wgTitle, $wgRequest;
+ global $wgUser, $wgOut, $wgTitle;
$resultDetails = false;
# Allow bots to exempt some edits from bot flagging
- $bot = $wgUser->isAllowed( 'bot' ) && $wgRequest->getBool( 'bot', true );
+ $bot = $wgUser->isAllowed( 'bot' ) && $this->bot;
$value = $this->internalAttemptSave( $resultDetails, $bot );
if ( $value == self::AS_SUCCESS_UPDATE || $value == self::AS_SUCCESS_NEW_ARTICLE ) {
} else {
return $this->mBaseRevision;
}
- }
+ }
}