summaryrefslogtreecommitdiff
path: root/includes/EditPage.php
diff options
context:
space:
mode:
Diffstat (limited to 'includes/EditPage.php')
-rw-r--r--includes/EditPage.php469
1 files changed, 236 insertions, 233 deletions
diff --git a/includes/EditPage.php b/includes/EditPage.php
index 38c80ba8..8d27eac8 100644
--- a/includes/EditPage.php
+++ b/includes/EditPage.php
@@ -151,6 +151,18 @@ class EditPage {
const AS_NO_CHANGE_CONTENT_MODEL = 235;
/**
+ * Status: user tried to create self-redirect (redirect to the same article) and
+ * wpIgnoreSelfRedirect == false
+ */
+ const AS_SELF_REDIRECT = 236;
+
+ /**
+ * Status: an error relating to change tagging. Look at the message key for
+ * more details
+ */
+ const AS_CHANGE_TAG_ERROR = 237;
+
+ /**
* Status: can't parse content
*/
const AS_PARSE_ERROR = 240;
@@ -256,6 +268,12 @@ class EditPage {
/** @var bool */
protected $allowBlankArticle = false;
+ /** @var bool */
+ protected $selfRedirect = false;
+
+ /** @var bool */
+ protected $allowSelfRedirect = false;
+
/** @var string */
public $autoSumm = '';
@@ -321,6 +339,9 @@ class EditPage {
/** @var int */
public $oldid = 0;
+ /** @var int */
+ public $parentRevId = 0;
+
/** @var string */
public $editintro = '';
@@ -336,6 +357,9 @@ class EditPage {
/** @var null|string */
public $contentFormat = null;
+ /** @var null|array */
+ public $changeTags = null;
+
# Placeholders for text injection by hooks (must be HTML)
# extensions should take care to _append_ to the present value
@@ -362,9 +386,6 @@ class EditPage {
/** @var bool */
protected $edit;
- /** @var bool */
- public $live;
-
/**
* @param Article $article
*/
@@ -448,29 +469,21 @@ class EditPage {
function edit() {
global $wgOut, $wgRequest, $wgUser;
// Allow extensions to modify/prevent this form or submission
- if ( !wfRunHooks( 'AlternateEdit', array( $this ) ) ) {
+ if ( !Hooks::run( 'AlternateEdit', array( $this ) ) ) {
return;
}
- wfProfileIn( __METHOD__ );
wfDebug( __METHOD__ . ": enter\n" );
// If they used redlink=1 and the page exists, redirect to the main article
if ( $wgRequest->getBool( 'redlink' ) && $this->mTitle->exists() ) {
$wgOut->redirect( $this->mTitle->getFullURL() );
- wfProfileOut( __METHOD__ );
return;
}
$this->importFormData( $wgRequest );
$this->firsttime = false;
- if ( $this->live ) {
- $this->livePreview();
- wfProfileOut( __METHOD__ );
- return;
- }
-
if ( wfReadOnly() && $this->save ) {
// Force preview
$this->save = false;
@@ -492,7 +505,7 @@ class EditPage {
}
}
- $permErrors = $this->getEditPermissionErrors();
+ $permErrors = $this->getEditPermissionErrors( $this->save ? 'secure' : 'full' );
if ( $permErrors ) {
wfDebug( __METHOD__ . ": User can't edit\n" );
// Auto-block user's IP if the account was "hard" blocked
@@ -500,12 +513,9 @@ class EditPage {
$this->displayPermissionsError( $permErrors );
- wfProfileOut( __METHOD__ );
return;
}
- wfProfileIn( __METHOD__ . "-business-end" );
-
$this->isConflict = false;
// css / js subpages of user pages get a special treatment
$this->isCssJsSubpage = $this->mTitle->isCssJsSubpage();
@@ -525,9 +535,9 @@ class EditPage {
# in the back door with a hand-edited submission URL.
if ( 'save' == $this->formtype ) {
- if ( !$this->attemptSave() ) {
- wfProfileOut( __METHOD__ . "-business-end" );
- wfProfileOut( __METHOD__ );
+ $resultDetails = null;
+ $status = $this->attemptSave( $resultDetails );
+ if ( !$this->handleStatus( $status, $resultDetails ) ) {
return;
}
}
@@ -537,34 +547,37 @@ class EditPage {
if ( 'initial' == $this->formtype || $this->firsttime ) {
if ( $this->initialiseForm() === false ) {
$this->noSuchSectionPage();
- wfProfileOut( __METHOD__ . "-business-end" );
- wfProfileOut( __METHOD__ );
return;
}
if ( !$this->mTitle->getArticleID() ) {
- wfRunHooks( 'EditFormPreloadText', array( &$this->textbox1, &$this->mTitle ) );
+ Hooks::run( 'EditFormPreloadText', array( &$this->textbox1, &$this->mTitle ) );
} else {
- wfRunHooks( 'EditFormInitialText', array( $this ) );
+ Hooks::run( 'EditFormInitialText', array( $this ) );
}
}
$this->showEditForm();
- wfProfileOut( __METHOD__ . "-business-end" );
- wfProfileOut( __METHOD__ );
}
/**
+ * @param string $rigor Same format as Title::getUserPermissionErrors()
* @return array
*/
- protected function getEditPermissionErrors() {
+ protected function getEditPermissionErrors( $rigor = 'secure' ) {
global $wgUser;
- $permErrors = $this->mTitle->getUserPermissionsErrors( 'edit', $wgUser );
+
+ $permErrors = $this->mTitle->getUserPermissionsErrors( 'edit', $wgUser, $rigor );
# Can this title be created?
if ( !$this->mTitle->exists() ) {
- $permErrors = array_merge( $permErrors,
- wfArrayDiff2( $this->mTitle->getUserPermissionsErrors( 'create', $wgUser ), $permErrors ) );
+ $permErrors = array_merge(
+ $permErrors,
+ wfArrayDiff2(
+ $this->mTitle->getUserPermissionsErrors( 'create', $wgUser, $rigor ),
+ $permErrors
+ )
+ );
}
# Ignore some permissions errors when a user is just previewing/viewing diffs
$remove = array();
@@ -576,6 +589,7 @@ class EditPage {
}
}
$permErrors = wfArrayDiff2( $permErrors, $remove );
+
return $permErrors;
}
@@ -612,7 +626,7 @@ class EditPage {
throw new PermissionsError( $action, $permErrors );
}
- wfRunHooks( 'EditPage::showReadOnlyForm:initial', array( $this, &$wgOut ) );
+ Hooks::run( 'EditPage::showReadOnlyForm:initial', array( $this, &$wgOut ) );
$wgOut->setRobotPolicy( 'noindex,nofollow' );
$wgOut->setPageTitle( wfMessage(
@@ -717,13 +731,10 @@ class EditPage {
function importFormData( &$request ) {
global $wgContLang, $wgUser;
- wfProfileIn( __METHOD__ );
-
# Section edit can come from either the form or a link
$this->section = $request->getVal( 'wpSection', $request->getVal( 'section' ) );
if ( $this->section !== null && $this->section !== '' && !$this->isSectionEditSupported() ) {
- wfProfileOut( __METHOD__ );
throw new ErrorPageError( 'sectioneditnotsupported-title', 'sectioneditnotsupported-text' );
}
@@ -738,13 +749,10 @@ class EditPage {
// Skip this if wpTextbox2 has input, it indicates that we came
// from a conflict page with raw page text, not a custom form
// modified by subclasses
- wfProfileIn( get_class( $this ) . "::importContentFormData" );
$textbox1 = $this->importContentFormData( $request );
if ( $textbox1 !== null ) {
$this->textbox1 = $textbox1;
}
-
- wfProfileOut( get_class( $this ) . "::importContentFormData" );
}
# Truncate for whole multibyte characters
@@ -785,7 +793,8 @@ class EditPage {
// TODO: softened the check for cutover. Once we determine
// that it is safe, we should complete the transition by
// removing the "edittime" clause.
- $this->incompleteForm = ( !$request->getVal( 'wpUltimateParam' ) && is_null( $this->edittime ) );
+ $this->incompleteForm = ( !$request->getVal( 'wpUltimateParam' )
+ && is_null( $this->edittime ) );
}
if ( $this->incompleteForm ) {
# If the form is incomplete, force to preview.
@@ -793,8 +802,7 @@ class EditPage {
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->preview = $request->getCheck( 'wpPreview' );
$this->diff = $request->getCheck( 'wpDiff' );
// Remember whether a save was requested, so we can indicate
@@ -844,6 +852,15 @@ class EditPage {
$this->autoSumm = $request->getText( 'wpAutoSummary' );
$this->allowBlankArticle = $request->getBool( 'wpIgnoreBlankArticle' );
+ $this->allowSelfRedirect = $request->getBool( 'wpIgnoreSelfRedirect' );
+
+ $changeTags = $request->getVal( 'wpChangeTags' );
+ if ( is_null( $changeTags ) || $changeTags === '' ) {
+ $this->changeTags = array();
+ } else {
+ $this->changeTags = array_filter( array_map( 'trim', explode( ',',
+ $changeTags ) ) );
+ }
} else {
# Not a posted form? Start with nothing.
wfDebug( __METHOD__ . ": Not a posted form.\n" );
@@ -880,6 +897,7 @@ class EditPage {
}
$this->oldid = $request->getInt( 'oldid' );
+ $this->parentRevId = $request->getInt( 'parentRevId' );
$this->bot = $request->getBool( 'bot', true );
$this->nosummary = $request->getBool( 'nosummary' );
@@ -905,15 +923,13 @@ class EditPage {
* allowed.
*/
- $this->live = $request->getCheck( 'live' );
$this->editintro = $request->getText( 'editintro',
// Custom edit intro for new sections
$this->section === 'new' ? 'MediaWiki:addsection-editintro' : '' );
// Allow extensions to modify form data
- wfRunHooks( 'EditPage::importFormData', array( $this, $request ) );
+ Hooks::run( 'EditPage::importFormData', array( $this, $request ) );
- wfProfileOut( __METHOD__ );
}
/**
@@ -974,8 +990,6 @@ class EditPage {
protected function getContentObject( $def_content = null ) {
global $wgOut, $wgRequest, $wgUser, $wgContLang;
- wfProfileIn( __METHOD__ );
-
$content = false;
// For message page not locally set, use the i18n message.
@@ -1087,7 +1101,6 @@ class EditPage {
}
}
- wfProfileOut( __METHOD__ );
return $content;
}
@@ -1280,18 +1293,20 @@ class EditPage {
/**
* Attempt submission
+ * @param array $resultDetails See docs for $result in internalAttemptSave
* @throws UserBlockedError|ReadOnlyError|ThrottledError|PermissionsError
- * @return bool False if output is done, true if the rest of the form should be displayed
+ * @return Status The resulting status object.
*/
- public function attemptSave() {
+ public function attemptSave( &$resultDetails = false ) {
global $wgUser;
- $resultDetails = false;
# Allow bots to exempt some edits from bot flagging
$bot = $wgUser->isAllowed( 'bot' ) && $this->bot;
$status = $this->internalAttemptSave( $resultDetails, $bot );
- return $this->handleStatus( $status, $resultDetails );
+ Hooks::run( 'EditPage::attemptSave:after', array( $this, $status, $resultDetails ) );
+
+ return $status;
}
/**
@@ -1329,6 +1344,7 @@ class EditPage {
case self::AS_MAX_ARTICLE_SIZE_EXCEEDED:
case self::AS_END:
case self::AS_BLANK_ARTICLE:
+ case self::AS_SELF_REDIRECT:
return true;
case self::AS_HOOK_ERROR:
@@ -1349,7 +1365,7 @@ class EditPage {
$sectionanchor = $resultDetails['sectionanchor'];
// Give extensions a chance to modify URL query on update
- wfRunHooks(
+ Hooks::run(
'ArticleUpdateBeforeRedirect',
array( $this->mArticle, &$sectionanchor, &$extraQuery )
);
@@ -1415,8 +1431,8 @@ class EditPage {
protected function runPostMergeFilters( Content $content, Status $status, User $user ) {
// Run old style post-section-merge edit filter
if ( !ContentHandler::runLegacyHooks( 'EditFilterMerged',
- array( $this, $content, &$this->hookError, $this->summary ) ) ) {
-
+ array( $this, $content, &$this->hookError, $this->summary ) )
+ ) {
# Error messages etc. could be handled within the hook...
$status->fatal( 'hookaborted' );
$status->value = self::AS_HOOK_ERROR;
@@ -1429,15 +1445,24 @@ class EditPage {
}
// Run new style post-section-merge edit filter
- if ( !wfRunHooks( 'EditFilterMergedContent',
- array( $this->mArticle->getContext(), $content, $status, $this->summary,
- $user, $this->minoredit ) ) ) {
-
+ if ( !Hooks::run( 'EditFilterMergedContent',
+ array( $this->mArticle->getContext(), $content, $status, $this->summary,
+ $user, $this->minoredit ) )
+ ) {
# Error messages etc. could be handled within the hook...
- // XXX: $status->value may already be something informative...
- $this->hookError = $status->getWikiText();
- $status->fatal( 'hookaborted' );
- $status->value = self::AS_HOOK_ERROR;
+ if ( $status->isGood() ) {
+ $status->fatal( 'hookaborted' );
+ // Not setting $this->hookError here is a hack to allow the hook
+ // to cause a return to the edit page without $this->hookError
+ // being set. This is used by ConfirmEdit to display a captcha
+ // without any error message cruft.
+ } else {
+ $this->hookError = $status->getWikiText();
+ }
+ // Use the existing $status->value if the hook set it
+ if ( !$status->value ) {
+ $status->value = self::AS_HOOK_ERROR;
+ }
return false;
} elseif ( !$status->isOK() ) {
# ...or the hook could be expecting us to produce an error
@@ -1510,15 +1535,10 @@ class EditPage {
$status = Status::newGood();
- wfProfileIn( __METHOD__ );
- wfProfileIn( __METHOD__ . '-checks' );
-
- if ( !wfRunHooks( 'EditPage::attemptSave', array( $this ) ) ) {
+ if ( !Hooks::run( 'EditPage::attemptSave', array( $this ) ) ) {
wfDebug( "Hook 'EditPage::attemptSave' aborted article saving\n" );
$status->fatal( 'hookaborted' );
$status->value = self::AS_HOOK_ERROR;
- wfProfileOut( __METHOD__ . '-checks' );
- wfProfileOut( __METHOD__ );
return $status;
}
@@ -1535,8 +1555,6 @@ class EditPage {
);
$status->fatal( 'spamprotectionmatch', false );
$status->value = self::AS_SPAM_ERROR;
- wfProfileOut( __METHOD__ . '-checks' );
- wfProfileOut( __METHOD__ );
return $status;
}
@@ -1551,8 +1569,6 @@ class EditPage {
$ex->getMessage()
);
$status->value = self::AS_PARSE_ERROR;
- wfProfileOut( __METHOD__ . '-checks' );
- wfProfileOut( __METHOD__ );
return $status;
}
@@ -1564,9 +1580,6 @@ class EditPage {
$code = $wgUser->isAnon() ? self::AS_IMAGE_REDIRECT_ANON : self::AS_IMAGE_REDIRECT_LOGGED;
$status->setResult( false, $code );
- wfProfileOut( __METHOD__ . '-checks' );
- wfProfileOut( __METHOD__ );
-
return $status;
}
@@ -1595,26 +1608,20 @@ class EditPage {
wfDebugLog( 'SpamRegex', "$ip spam regex hit [[$pdbk]]: \"$match\"" );
$status->fatal( 'spamprotectionmatch', $match );
$status->value = self::AS_SPAM_ERROR;
- wfProfileOut( __METHOD__ . '-checks' );
- wfProfileOut( __METHOD__ );
return $status;
}
- if ( !wfRunHooks(
+ 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;
- wfProfileOut( __METHOD__ . '-checks' );
- wfProfileOut( __METHOD__ );
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;
- wfProfileOut( __METHOD__ . '-checks' );
- wfProfileOut( __METHOD__ );
return $status;
}
@@ -1623,8 +1630,6 @@ class EditPage {
$wgUser->spreadAnyEditBlock();
# Check block state against master, thus 'false'.
$status->setResult( false, self::AS_BLOCKED_PAGE_FOR_USER );
- wfProfileOut( __METHOD__ . '-checks' );
- wfProfileOut( __METHOD__ );
return $status;
}
@@ -1633,22 +1638,16 @@ class EditPage {
// Error will be displayed by showEditForm()
$this->tooBig = true;
$status->setResult( false, self::AS_CONTENT_TOO_BIG );
- wfProfileOut( __METHOD__ . '-checks' );
- wfProfileOut( __METHOD__ );
return $status;
}
if ( !$wgUser->isAllowed( 'edit' ) ) {
if ( $wgUser->isAnon() ) {
$status->setResult( false, self::AS_READ_ONLY_PAGE_ANON );
- wfProfileOut( __METHOD__ . '-checks' );
- wfProfileOut( __METHOD__ );
return $status;
} else {
$status->fatal( 'readonlytext' );
$status->value = self::AS_READ_ONLY_PAGE_LOGGED;
- wfProfileOut( __METHOD__ . '-checks' );
- wfProfileOut( __METHOD__ );
return $status;
}
}
@@ -1657,23 +1656,26 @@ class EditPage {
&& !$wgUser->isAllowed( 'editcontentmodel' )
) {
$status->setResult( false, self::AS_NO_CHANGE_CONTENT_MODEL );
- wfProfileOut( __METHOD__ . '-checks' );
- wfProfileOut( __METHOD__ );
return $status;
}
+ 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;
- wfProfileOut( __METHOD__ . '-checks' );
- wfProfileOut( __METHOD__ );
return $status;
}
if ( $wgUser->pingLimiter() || $wgUser->pingLimiter( 'linkpurge', 0 ) ) {
$status->fatal( 'actionthrottledtext' );
$status->value = self::AS_RATE_LIMITED;
- wfProfileOut( __METHOD__ . '-checks' );
- wfProfileOut( __METHOD__ );
return $status;
}
@@ -1681,13 +1683,9 @@ class EditPage {
# confirmation
if ( $this->wasDeletedSinceLastEdit() && !$this->recreate ) {
$status->setResult( false, self::AS_ARTICLE_WAS_DELETED );
- wfProfileOut( __METHOD__ . '-checks' );
- wfProfileOut( __METHOD__ );
return $status;
}
- wfProfileOut( __METHOD__ . '-checks' );
-
# 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->mArticle->loadPageData( 'fromdbmaster' );
@@ -1699,7 +1697,6 @@ class EditPage {
$status->fatal( 'nocreatetext' );
$status->value = self::AS_NO_CREATE_PERMISSION;
wfDebug( __METHOD__ . ": no create permission\n" );
- wfProfileOut( __METHOD__ );
return $status;
}
@@ -1717,12 +1714,10 @@ class EditPage {
$this->blankArticle = true;
$status->fatal( 'blankarticle' );
$status->setResult( false, self::AS_BLANK_ARTICLE );
- wfProfileOut( __METHOD__ );
return $status;
}
if ( !$this->runPostMergeFilters( $textbox_content, $status, $wgUser ) ) {
- wfProfileOut( __METHOD__ );
return $status;
}
@@ -1827,12 +1822,10 @@ class EditPage {
if ( $this->isConflict ) {
$status->setResult( false, self::AS_CONFLICT_DETECTED );
- wfProfileOut( __METHOD__ );
return $status;
}
if ( !$this->runPostMergeFilters( $content, $status, $wgUser ) ) {
- wfProfileOut( __METHOD__ );
return $status;
}
@@ -1842,7 +1835,6 @@ class EditPage {
$this->missingSummary = true;
$status->fatal( 'missingsummary' ); // or 'missingcommentheader' if $section == 'new'. Blegh
$status->value = self::AS_SUMMARY_NEEDED;
- wfProfileOut( __METHOD__ );
return $status;
}
@@ -1851,7 +1843,6 @@ class EditPage {
$this->missingComment = true;
$status->fatal( 'missingcommenttext' );
$status->value = self::AS_TEXTBOX_EMPTY;
- wfProfileOut( __METHOD__ );
return $status;
}
} elseif ( !$this->allowBlankSummary
@@ -1862,12 +1853,10 @@ class EditPage {
$this->missingSummary = true;
$status->fatal( 'missingsummary' );
$status->value = self::AS_SUMMARY_NEEDED;
- wfProfileOut( __METHOD__ );
return $status;
}
# All's well
- wfProfileIn( __METHOD__ . '-sectionanchor' );
$sectionanchor = '';
if ( $this->section == 'new' ) {
$this->summary = $this->newSectionSummary( $sectionanchor );
@@ -1884,7 +1873,6 @@ class EditPage {
}
}
$result['sectionanchor'] = $sectionanchor;
- wfProfileOut( __METHOD__ . '-sectionanchor' );
// Save errors may fall down to the edit form, but we've now
// merged the section into full text. Clear the section field
@@ -1896,12 +1884,25 @@ class EditPage {
$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 );
- wfProfileOut( __METHOD__ );
return $status;
}
@@ -1931,7 +1932,6 @@ class EditPage {
// Destroys data doEdit() put in $status->value but who cares
$doEditStatus->value = self::AS_END;
}
- wfProfileOut( __METHOD__ );
return $doEditStatus;
}
@@ -1941,8 +1941,18 @@ class EditPage {
$wgUser->pingLimiter( 'linkpurge' );
}
$result['redirect'] = $content->isRedirect();
+
$this->updateWatchlist();
- wfProfileOut( __METHOD__ );
+
+ if ( $this->changeTags && isset( $doEditStatus->value['revision'] ) ) {
+ // If a revision was created, apply any change tags that were requested
+ ChangeTags::addTags(
+ $this->changeTags,
+ isset( $doEditStatus->value['rc'] ) ? $doEditStatus->value['rc']->mAttribs['rc_id'] : null,
+ $doEditStatus->value['revision']->getId()
+ );
+ }
+
return $status;
}
@@ -1979,7 +1989,6 @@ class EditPage {
* @return bool
*/
private function mergeChangesIntoContent( &$editContent ) {
- wfProfileIn( __METHOD__ );
$db = wfGetDB( DB_MASTER );
@@ -1988,7 +1997,6 @@ class EditPage {
$baseContent = $baseRevision ? $baseRevision->getContent() : null;
if ( is_null( $baseContent ) ) {
- wfProfileOut( __METHOD__ );
return false;
}
@@ -1997,7 +2005,6 @@ class EditPage {
$currentContent = $currentRevision ? $currentRevision->getContent() : null;
if ( is_null( $currentContent ) ) {
- wfProfileOut( __METHOD__ );
return false;
}
@@ -2007,11 +2014,9 @@ class EditPage {
if ( $result ) {
$editContent = $result;
- wfProfileOut( __METHOD__ );
return true;
}
- wfProfileOut( __METHOD__ );
return false;
}
@@ -2070,19 +2075,31 @@ class EditPage {
}
function setHeaders() {
- global $wgOut, $wgUser;
+ global $wgOut, $wgUser, $wgAjaxEditStash;
$wgOut->addModules( 'mediawiki.action.edit' );
$wgOut->addModuleStyles( 'mediawiki.action.edit.styles' );
- if ( $wgUser->getOption( 'uselivepreview', false ) ) {
+ if ( $wgUser->getOption( 'showtoolbar' ) ) {
+ // The addition of default buttons is handled by getEditToolbar() which
+ // has its own dependency on this module. The call here ensures the module
+ // is loaded in time (it has position "top") for other modules to register
+ // buttons (e.g. extensions, gadgets, user scripts).
+ $wgOut->addModules( 'mediawiki.toolbar' );
+ }
+
+ if ( $wgUser->getOption( 'uselivepreview' ) ) {
$wgOut->addModules( 'mediawiki.action.edit.preview' );
}
- if ( $wgUser->getOption( 'useeditwarning', false ) ) {
+ if ( $wgUser->getOption( 'useeditwarning' ) ) {
$wgOut->addModules( 'mediawiki.action.edit.editWarning' );
}
+ if ( $wgAjaxEditStash ) {
+ $wgOut->addModules( 'mediawiki.action.edit.stash' );
+ }
+
$wgOut->setRobotPolicy( 'noindex,nofollow' );
# Enabled article-related sidebar, toplinks, etc.
@@ -2108,6 +2125,9 @@ class EditPage {
$displayTitle = $contextTitle->getPrefixedText();
}
$wgOut->setPageTitle( wfMessage( $msg, $displayTitle ) );
+ # Transmit the name of the message to JavaScript for live preview
+ # Keep Resources.php/mediawiki.action.edit.preview in sync with the possible keys
+ $wgOut->addJsConfigVars( 'wgEditMessage', $msg );
}
/**
@@ -2124,6 +2144,17 @@ class EditPage {
if ( $namespace == NS_MEDIAWIKI ) {
# Show a warning if editing an interface message
$wgOut->wrapWikiMsg( "<div class='mw-editinginterface'>\n$1\n</div>", 'editinginterface' );
+ # If this is a default message (but not css or js),
+ # show a hint that it is translatable on translatewiki.net
+ if ( !$this->mTitle->hasContentModel( CONTENT_MODEL_CSS )
+ && !$this->mTitle->hasContentModel( CONTENT_MODEL_JAVASCRIPT )
+ ) {
+ $defaultMessageText = $this->mTitle->getDefaultMessageText();
+ if ( $defaultMessageText !== false ) {
+ $wgOut->wrapWikiMsg( "<div class='mw-translateinterface'>\n$1\n</div>",
+ 'translateinterface' );
+ }
+ }
} elseif ( $namespace == NS_FILE ) {
# Show a hint to shared repo
$file = wfFindFile( $this->mTitle );
@@ -2155,7 +2186,8 @@ class EditPage {
if ( !( $user && $user->isLoggedIn() ) && !$ip ) { # User does not exist
$wgOut->wrapWikiMsg( "<div class=\"mw-userpage-userdoesnotexist error\">\n$1\n</div>",
array( 'userpage-userdoesnotexist', wfEscapeWikiText( $username ) ) );
- } elseif ( !is_null( $block ) && $block->getType() != Block::TYPE_AUTO ) { # Show log extract if the user is currently blocked
+ } elseif ( !is_null( $block ) && $block->getType() != Block::TYPE_AUTO ) {
+ # Show log extract if the user is currently blocked
LogEventsList::showLogExtract(
$wgOut,
'block',
@@ -2222,7 +2254,10 @@ class EditPage {
if ( $title instanceof Title && $title->exists() && $title->userCan( 'read' ) ) {
global $wgOut;
// Added using template syntax, to take <noinclude>'s into account.
- $wgOut->addWikiTextTitleTidy( '<div class="mw-editintro">{{:' . $title->getFullText() . '}}</div>', $this->mTitle );
+ $wgOut->addWikiTextTitleTidy(
+ '<div class="mw-editintro">{{:' . $title->getFullText() . '}}</div>',
+ $this->mTitle
+ );
return true;
}
}
@@ -2248,11 +2283,7 @@ class EditPage {
* $this->allowNonTextContent is not true.
*/
protected function toEditText( $content ) {
- if ( $content === null || $content === false ) {
- return $content;
- }
-
- if ( is_string( $content ) ) {
+ if ( $content === null || $content === false || is_string( $content ) ) {
return $content;
}
@@ -2300,12 +2331,13 @@ class EditPage {
* Send the edit form and related headers to $wgOut
* @param callable|null $formCallback That takes an OutputPage parameter; will be called
* during form output near the top, for captchas and the like.
+ *
+ * The $formCallback parameter is deprecated since MediaWiki 1.25. Please
+ * use the EditPage::showEditForm:fields hook instead.
*/
function showEditForm( $formCallback = null ) {
global $wgOut, $wgUser;
- wfProfileIn( __METHOD__ );
-
# need to parse the preview early so that we know which templates are used,
# otherwise users with "show preview after edit box" will get a blank list
# we parse this near the beginning so that setHeaders can do the title
@@ -2315,12 +2347,11 @@ class EditPage {
$previewOutput = $this->getPreviewText();
}
- wfRunHooks( 'EditPage::showEditForm:initial', array( &$this, &$wgOut ) );
+ Hooks::run( 'EditPage::showEditForm:initial', array( &$this, &$wgOut ) );
$this->setHeaders();
if ( $this->showHeader() === false ) {
- wfProfileOut( __METHOD__ );
return;
}
@@ -2358,6 +2389,7 @@ class EditPage {
) );
if ( is_callable( $formCallback ) ) {
+ wfWarn( 'The $formCallback parameter to ' . __METHOD__ . 'is deprecated' );
call_user_func_array( $formCallback, array( &$wgOut ) );
}
@@ -2381,7 +2413,7 @@ class EditPage {
. Xml::closeElement( 'div' )
);
- wfRunHooks( 'EditPage::showEditForm:fields', array( &$this, &$wgOut ) );
+ Hooks::run( 'EditPage::showEditForm:fields', array( &$this, &$wgOut ) );
// Put these up at the top to ensure they aren't lost on early form submission
$this->showFormBeforeText();
@@ -2425,6 +2457,10 @@ class EditPage {
$wgOut->addHTML( Html::hidden( 'wpUndidRevision', $this->undidRev ) );
}
+ if ( $this->selfRedirect ) {
+ $wgOut->addHTML( Html::hidden( 'wpIgnoreSelfRedirect', true ) );
+ }
+
if ( $this->hasPresetSummary ) {
// If a summary has been preset using &summary= we don't want to prompt for
// a different summary. Only prompt for a summary if the summary is blanked.
@@ -2436,6 +2472,8 @@ class EditPage {
$wgOut->addHTML( Html::hidden( 'wpAutoSummary', $autosumm ) );
$wgOut->addHTML( Html::hidden( 'oldid', $this->oldid ) );
+ $wgOut->addHTML( Html::hidden( 'parentRevId',
+ $this->parentRevId ?: $this->mArticle->getRevIdFetched() ) );
$wgOut->addHTML( Html::hidden( 'format', $this->contentFormat ) );
$wgOut->addHTML( Html::hidden( 'model', $this->contentModel ) );
@@ -2517,7 +2555,6 @@ class EditPage {
$this->displayPreviewArea( $previewOutput, false );
}
- wfProfileOut( __METHOD__ );
}
/**
@@ -2548,7 +2585,19 @@ class EditPage {
}
// Add edit notices
- $wgOut->addHTML( implode( "\n", $this->mTitle->getEditNotices( $this->oldid ) ) );
+ $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' );
@@ -2587,6 +2636,10 @@ class EditPage {
$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 );
}
@@ -2846,7 +2899,7 @@ class EditPage {
global $wgOut;
$section = htmlspecialchars( $this->section );
$wgOut->addHTML( <<<HTML
-<input type='hidden' value="{$section}" name="wpSection" />
+<input type='hidden' value="{$section}" name="wpSection"/>
<input type='hidden' value="{$this->starttime}" name="wpStarttime" />
<input type='hidden' value="{$this->edittime}" name="wpEdittime" />
<input type='hidden' value="{$this->scrolltop}" name="wpScrolltop" id="wpScrolltop" />
@@ -2964,7 +3017,7 @@ HTML
);
$pageLang = $this->mTitle->getPageLanguage();
- $attribs['lang'] = $pageLang->getCode();
+ $attribs['lang'] = $pageLang->getHtmlCode();
$attribs['dir'] = $pageLang->getDir();
$wgOut->addHTML( Html::textarea( $name, $wikitext, $attribs ) );
@@ -2987,6 +3040,12 @@ HTML
if ( $this->formtype == 'preview' ) {
$this->showPreview( $previewOutput );
+ } else {
+ // Empty content container for LivePreview
+ $pageViewLang = $this->mTitle->getPageViewLanguage();
+ $attribs = array( 'lang' => $pageViewLang->getHtmlCode(), 'dir' => $pageViewLang->getDir(),
+ 'class' => 'mw-content-' . $pageViewLang->getDir() );
+ $wgOut->addHTML( Html::rawElement( 'div', $attribs ) );
}
$wgOut->addHTML( '</div>' );
@@ -3019,7 +3078,7 @@ HTML
}
# This hook seems slightly odd here, but makes things more
# consistent for extensions.
- wfRunHooks( 'OutputPageBeforeHTML', array( &$wgOut, &$text ) );
+ Hooks::run( 'OutputPageBeforeHTML', array( &$wgOut, &$text ) );
$wgOut->addHTML( $text );
if ( $this->mTitle->getNamespace() == NS_CATEGORY ) {
$this->mArticle->closeShowCategory();
@@ -3058,7 +3117,7 @@ HTML
if ( $newContent ) {
ContentHandler::runLegacyHooks( 'EditPageGetDiffText', array( $this, &$newContent ) );
- wfRunHooks( 'EditPageGetDiffContent', array( $this, &$newContent ) );
+ Hooks::run( 'EditPageGetDiffContent', array( $this, &$newContent ) );
$popts = ParserOptions::newFromUserAndLang( $wgUser, $wgContLang );
$newContent = $newContent->preSaveTransform( $this->mTitle, $wgUser, $popts );
@@ -3110,7 +3169,7 @@ HTML
*/
protected function showTosSummary() {
$msg = 'editpage-tos-summary';
- wfRunHooks( 'EditPageTosSummary', array( $this->mTitle, &$msg ) );
+ Hooks::run( 'EditPageTosSummary', array( $this->mTitle, &$msg ) );
if ( !wfMessage( $msg )->isDisabled() ) {
global $wgOut;
$wgOut->addHTML( '<div class="mw-tos-summary">' );
@@ -3154,7 +3213,7 @@ HTML
'[[' . wfMessage( 'copyrightpage' )->inContentLanguage()->text() . ']]' );
}
// Allow for site and per-namespace customization of contribution/copyright notice.
- wfRunHooks( 'EditPageCopyrightWarning', array( $title, &$copywarnMsg ) );
+ Hooks::run( 'EditPageCopyrightWarning', array( $title, &$copywarnMsg ) );
return "<div id=\"editpage-copywarn\">\n" .
call_user_func_array( 'wfMessage', $copywarnMsg )->$format() . "\n</div>";
@@ -3172,8 +3231,6 @@ HTML
return '';
}
- wfProfileIn( __METHOD__ );
-
$limitReport = Html::rawElement( 'div', array( 'class' => 'mw-limitReportExplanation' ),
wfMessage( 'limitreport-title' )->parseAsBlock()
);
@@ -3187,7 +3244,7 @@ HTML
Html::openElement( 'tbody' );
foreach ( $output->getLimitReportData() as $key => $value ) {
- if ( wfRunHooks( 'ParserLimitReportFormat',
+ if ( Hooks::run( 'ParserLimitReportFormat',
array( $key, &$value, &$limitReport, true, true )
) ) {
$keyMsg = wfMessage( $key );
@@ -3208,13 +3265,11 @@ HTML
Html::closeElement( 'table' ) .
Html::closeElement( 'div' );
- wfProfileOut( __METHOD__ );
-
return $limitReport;
}
protected function showStandardInputs( &$tabindex = 2 ) {
- global $wgOut, $wgUseMediaWikiUIEverywhere;
+ global $wgOut;
$wgOut->addHTML( "<div class='editOptions'>\n" );
if ( $this->section != 'new' ) {
@@ -3246,10 +3301,8 @@ HTML
'target' => 'helpwindow',
'href' => $edithelpurl,
);
- if ( $wgUseMediaWikiUIEverywhere ) {
- $attrs['class'] = 'mw-ui-button mw-ui-quiet';
- }
- $edithelp = Html::element( 'a', $attrs, wfMessage( 'edithelp' )->text() ) .
+ $edithelp = Html::linkButton( wfMessage( 'edithelp' )->text(),
+ $attrs, array( 'mw-ui-quiet' ) ) .
wfMessage( 'word-separator' )->escaped() .
wfMessage( 'newwindow' )->parse();
@@ -3257,7 +3310,7 @@ HTML
$wgOut->addHTML( " <span class='editHelp'>{$edithelp}</span>\n" );
$wgOut->addHTML( "</div><!-- editButtons -->\n" );
- wfRunHooks( 'EditPage::showStandardInputs:options', array( $this, $wgOut, &$tabindex ) );
+ Hooks::run( 'EditPage::showStandardInputs:options', array( $this, $wgOut, &$tabindex ) );
$wgOut->addHTML( "</div><!-- editOptions -->\n" );
}
@@ -3269,7 +3322,7 @@ HTML
protected function showConflict() {
global $wgOut;
- if ( wfRunHooks( 'EditPageBeforeConflictDiff', array( &$this, &$wgOut ) ) ) {
+ if ( Hooks::run( 'EditPageBeforeConflictDiff', array( &$this, &$wgOut ) ) ) {
$wgOut->wrapWikiMsg( '<h2>$1</h2>', "yourdiff" );
$content1 = $this->toEditContent( $this->textbox1 );
@@ -3292,20 +3345,16 @@ HTML
* @return string
*/
public function getCancelLink() {
- global $wgUseMediaWikiUIEverywhere;
$cancelParams = array();
if ( !$this->isConflict && $this->oldid > 0 ) {
$cancelParams['oldid'] = $this->oldid;
}
$attrs = array( 'id' => 'mw-editform-cancel' );
- if ( $wgUseMediaWikiUIEverywhere ) {
- $attrs['class'] = 'mw-ui-button mw-ui-quiet';
- }
return Linker::linkKnown(
$this->getContextTitle(),
wfMessage( 'cancel' )->parse(),
- $attrs,
+ Html::buttonAttributes( $attrs, array( 'mw-ui-quiet' ) ),
$cancelParams
);
}
@@ -3401,8 +3450,6 @@ HTML
global $wgOut, $wgUser, $wgRawHtml, $wgLang;
global $wgAllowUserCss, $wgAllowUserJs;
- wfProfileIn( __METHOD__ );
-
if ( $wgRawHtml && !$this->mTokenOk ) {
// Could be an offsite preview attempt. This is very unsafe if
// HTML is enabled, as it could be an attack.
@@ -3414,7 +3461,6 @@ HTML
$parsedNote = $wgOut->parse( "<div class='previewnote'>" .
wfMessage( 'session_fail_preview_html' )->text() . "</div>", true, /* interface */true );
}
- wfProfileOut( __METHOD__ );
return $parsedNote;
}
@@ -3424,11 +3470,10 @@ HTML
$content = $this->toEditContent( $this->textbox1 );
$previewHTML = '';
- if ( !wfRunHooks(
+ if ( !Hooks::run(
'AlternateEditPreview',
array( $this, &$content, &$previewHTML, &$this->mParserOutput ) )
) {
- wfProfileOut( __METHOD__ );
return $previewHTML;
}
@@ -3449,7 +3494,6 @@ HTML
}
$parserOptions = $this->mArticle->makeParserOptions( $this->mArticle->getContext() );
- $parserOptions->setEditSection( false );
$parserOptions->setIsPreview( true );
$parserOptions->setIsSectionPreview( !is_null( $this->section ) && $this->section !== '' );
@@ -3494,20 +3538,26 @@ HTML
$hook_args = array( $this, &$content );
ContentHandler::runLegacyHooks( 'EditPageGetPreviewText', $hook_args );
- wfRunHooks( 'EditPageGetPreviewContent', $hook_args );
+ Hooks::run( 'EditPageGetPreviewContent', $hook_args );
$parserOptions->enableLimitReport();
# For CSS/JS pages, we should have called the ShowRawCssJs hook here.
# But it's now deprecated, so never mind
- $content = $content->preSaveTransform( $this->mTitle, $wgUser, $parserOptions );
- $parserOutput = $content->getParserOutput(
- $this->getArticle()->getTitle(),
- null,
- $parserOptions
+ $pstContent = $content->preSaveTransform( $this->mTitle, $wgUser, $parserOptions );
+ $scopedCallback = $parserOptions->setupFakeRevision(
+ $this->mTitle, $pstContent, $wgUser );
+ $parserOutput = $pstContent->getParserOutput( $this->mTitle, null, $parserOptions );
+
+ # Try to stash the edit for the final submission step
+ # @todo: different date format preferences cause cache misses
+ ApiStashEdit::stashEditFromPreview(
+ $this->getArticle(), $content, $pstContent,
+ $parserOutput, $parserOptions, $parserOptions, wfTimestampNow()
);
+ $parserOutput->setEditSectionTokens( false ); // no section edit links
$previewHTML = $parserOutput->getText();
$this->mParserOutput = $parserOutput;
$wgOut->addParserOutputMetadata( $parserOutput );
@@ -3542,7 +3592,6 @@ HTML
'class' => 'mw-content-' . $pageViewLang->getDir() );
$previewHTML = Html::rawElement( 'div', $attribs, $previewHTML );
- wfProfileOut( __METHOD__ );
return $previewhead . $previewHTML . $this->previewTextAfterContent;
}
@@ -3660,7 +3709,7 @@ HTML
)
);
- $script = 'mw.loader.using("mediawiki.action.edit", function() {';
+ $script = 'mw.loader.using("mediawiki.toolbar", function () {';
foreach ( $toolarray as $tool ) {
if ( !$tool ) {
continue;
@@ -3680,21 +3729,19 @@ HTML
$tool['id'],
);
- $script .= Xml::encodeJsCall( 'mw.toolbar.addButton', $params );
+ $script .= Xml::encodeJsCall(
+ 'mw.toolbar.addButton',
+ $params,
+ ResourceLoader::inDebugMode()
+ );
}
- // This used to be called on DOMReady from mediawiki.action.edit, which
- // ended up causing race conditions with the setup code above.
- $script .= "\n" .
- "// Create button bar\n" .
- "$(function() { mw.toolbar.init(); } );\n";
-
$script .= '});';
$wgOut->addScript( Html::inlineScript( ResourceLoader::makeLoaderConditionalScript( $script ) ) );
$toolbar = '<div id="toolbar"></div>';
- wfRunHooks( 'EditPageBeforeEditToolbar', array( &$toolbar ) );
+ Hooks::run( 'EditPageBeforeEditToolbar', array( &$toolbar ) );
return $toolbar;
}
@@ -3761,7 +3808,7 @@ HTML
$checkboxes['watch'] = $watchThisHtml;
}
}
- wfRunHooks( 'EditPageBeforeEditChecks', array( &$this, &$checkboxes, &$tabindex ) );
+ Hooks::run( 'EditPageBeforeEditChecks', array( &$this, &$checkboxes, &$tabindex ) );
return $checkboxes;
}
@@ -3774,83 +3821,39 @@ HTML
* @return array
*/
public function getEditButtons( &$tabindex ) {
- global $wgUseMediaWikiUIEverywhere;
-
$buttons = array();
$attribs = array(
'id' => 'wpSave',
'name' => 'wpSave',
- 'type' => 'submit',
'tabindex' => ++$tabindex,
- 'value' => wfMessage( 'savearticle' )->text(),
) + Linker::tooltipAndAccesskeyAttribs( 'save' );
- if ( $wgUseMediaWikiUIEverywhere ) {
- $attribs['class'] = 'mw-ui-button mw-ui-constructive';
- }
- $buttons['save'] = Xml::element( 'input', $attribs, '' );
+ $buttons['save'] = Html::submitButton( wfMessage( 'savearticle' )->text(),
+ $attribs, array( 'mw-ui-constructive' ) );
++$tabindex; // use the same for preview and live preview
$attribs = array(
'id' => 'wpPreview',
'name' => 'wpPreview',
- 'type' => 'submit',
'tabindex' => $tabindex,
- 'value' => wfMessage( 'showpreview' )->text(),
) + Linker::tooltipAndAccesskeyAttribs( 'preview' );
- if ( $wgUseMediaWikiUIEverywhere ) {
- $attribs['class'] = 'mw-ui-button mw-ui-progressive';
- }
- $buttons['preview'] = Xml::element( 'input', $attribs, '' );
+ $buttons['preview'] = Html::submitButton( wfMessage( 'showpreview' )->text(),
+ $attribs );
$buttons['live'] = '';
$attribs = array(
'id' => 'wpDiff',
'name' => 'wpDiff',
- 'type' => 'submit',
'tabindex' => ++$tabindex,
- 'value' => wfMessage( 'showdiff' )->text(),
) + Linker::tooltipAndAccesskeyAttribs( 'diff' );
- if ( $wgUseMediaWikiUIEverywhere ) {
- $attribs['class'] = 'mw-ui-button mw-ui-progressive';
- }
- $buttons['diff'] = Xml::element( 'input', $attribs, '' );
+ $buttons['diff'] = Html::submitButton( wfMessage( 'showdiff' )->text(),
+ $attribs );
- wfRunHooks( 'EditPageBeforeEditButtons', array( &$this, &$buttons, &$tabindex ) );
+ Hooks::run( 'EditPageBeforeEditButtons', array( &$this, &$buttons, &$tabindex ) );
return $buttons;
}
/**
- * Output preview text only. This can be sucked into the edit page
- * via JavaScript, and saves the server time rendering the skin as
- * well as theoretically being more robust on the client (doesn't
- * disturb the edit box's undo history, won't eat your text on
- * failure, etc).
- *
- * @todo This doesn't include category or interlanguage links.
- * Would need to enhance it a bit, "<s>maybe wrap them in XML
- * or something...</s>" that might also require more skin
- * initialization, so check whether that's a problem.
- */
- function livePreview() {
- global $wgOut;
- $wgOut->disable();
- header( 'Content-type: text/xml; charset=utf-8' );
- header( 'Cache-control: no-cache' );
-
- $previewText = $this->getPreviewText();
- #$categories = $skin->getCategoryLinks();
-
- $s =
- '<?xml version="1.0" encoding="UTF-8" ?>' . "\n" .
- Xml::tags( 'livepreview', null,
- Xml::element( 'preview', null, $previewText )
- #. Xml::element( 'category', null, $categories )
- );
- echo $s;
- }
-
- /**
* Creates a basic error page which informs the user that
* they have attempted to edit a nonexistent section.
*/
@@ -3860,7 +3863,7 @@ HTML
$wgOut->prepareErrorPage( wfMessage( 'nosuchsectiontitle' ) );
$res = wfMessage( 'nosuchsectiontext', $this->section )->parseAsBlock();
- wfRunHooks( 'EditPageNoSuchSection', array( &$this, &$res ) );
+ Hooks::run( 'EditPageNoSuchSection', array( &$this, &$res ) );
$wgOut->addHTML( $res );
$wgOut->returnToMain( false, $this->mTitle );
@@ -4018,9 +4021,9 @@ HTML
// Do some sanity checks. These aren't needed for reversibility,
// but should help keep the breakage down if the editor
// breaks one of the entities whilst editing.
- if ( ( substr( $invalue, $i, 1 ) == ";" ) and ( strlen( $hexstring ) <= 6 ) ) {
+ if ( ( substr( $invalue, $i, 1 ) == ";" ) && ( strlen( $hexstring ) <= 6 ) ) {
$codepoint = hexdec( $hexstring );
- $result .= codepointToUtf8( $codepoint );
+ $result .= UtfNormal\Utils::codepointToUtf8( $codepoint );
} else {
$result .= "&#x" . $hexstring . substr( $invalue, $i, 1 );
}