jenkins-bot has submitted this change and it was merged.
Change subject: Edit conflicts
......................................................................
Edit conflicts
Done:
* Header: Non-JS
* Header: JS
* Title: Non-JS
* Title: JS
* Post: Non-JS
* Post: JS
Note: there's some duplication of tipsy code. Not sure how I feel about that.
Change-Id: I70fc7384eb0fb9929db0ad478dc624a22f7fe6a5
---
M Resources.php
M includes/Block/Header.php
M includes/Block/Topic.php
M modules/base/action.js
M modules/base/ext.flow.base.js
M modules/base/styles/actionbox.less
M modules/base/ui-functions.js
M modules/discussion/post.js
M modules/discussion/topic.js
M modules/header/forms.js
M templates/edit-header.html.php
M templates/edit-post.html.php
M templates/edit-title.html.php
13 files changed, 368 insertions(+), 29 deletions(-)
Approvals:
EBernhardson: Looks good to me, approved
jenkins-bot: Verified
diff --git a/Resources.php b/Resources.php
index c3f97e4..1f7d3e5 100644
--- a/Resources.php
+++ b/Resources.php
@@ -33,6 +33,7 @@
'mediawiki.ui',
'mediawiki.api',
'jquery.json',
+ 'jquery.tipsy',
),
'messages' => array(
'flow-preview',
@@ -48,6 +49,8 @@
),
'messages' => array(
'flow-error-other',
+ 'flow-edit-header-submit',
+ 'flow-edit-header-submit-overwrite',
),
),
'ext.flow.discussion' => $flowResourceTemplate + array(
@@ -87,10 +90,11 @@
'flow-error-external',
'flow-error-external-multi',
'flow-edit-title-submit',
+ 'flow-edit-title-submit-overwrite',
'flow-edit-post-submit',
+ 'flow-edit-post-submit-overwrite',
'flow-paging-fwd',
'flow-paging-rev',
- 'flow-edit-header-submit',
'flow-post-moderated-toggle-show',
'flow-post-moderated-toggle-hide',
'flow-terms-of-use-edit',
diff --git a/includes/Block/Header.php b/includes/Block/Header.php
index 3786b07..eda5f82 100644
--- a/includes/Block/Header.php
+++ b/includes/Block/Header.php
@@ -76,7 +76,8 @@
// handing user back to specific dialog
indicating race condition
$this->addError(
'prev_revision',
- wfMessage(
'flow-error-prev-revision-mismatch' )->params(
$this->submitted['prev_revision'], $this->header->getRevisionId()->getHex() )
+ wfMessage(
'flow-error-prev-revision-mismatch' )->params(
$this->submitted['prev_revision'], $this->header->getRevisionId()->getHex() ),
+ array( 'revision_id' =>
$this->header->getRevisionId()->getHex() ) // save current revision ID
);
}
diff --git a/includes/Block/Topic.php b/includes/Block/Topic.php
index f81b43c..2796220 100644
--- a/includes/Block/Topic.php
+++ b/includes/Block/Topic.php
@@ -130,14 +130,30 @@
if ( $len > PostRevision::MAX_TOPIC_LENGTH ) {
$this->addError( 'content', wfMessage(
'flow-error-title-too-long', PostRevision::MAX_TOPIC_LENGTH ) );
return;
- }
- $topicTitle = $this->loadTopicTitle();
- if ( !$topicTitle ) {
- throw new InvalidInputException( 'No revision
associated with workflow?', 'missing-revision' );
- }
- if ( !$this->permissions->isAllowed( $topicTitle, 'edit-title'
) ) {
- $this->addError( 'permissions', wfMessage(
'flow-error-not-allowed' ) );
+ } elseif ( empty( $this->submitted['prev_revision'] ) ) {
+ $this->addError( 'prev_revision', wfMessage(
'flow-error-missing-prev-revision-identifier' ) );
return;
+ } else {
+ $topicTitle = $this->loadTopicTitle();
+ if ( !$topicTitle ) {
+ throw new InvalidInputException( 'No revision
associated with workflow?', 'missing-revision' );
+ }
+ if ( !$this->permissions->isAllowed( $topicTitle,
'edit-title' ) ) {
+ $this->addError( 'permissions', wfMessage(
'flow-error-not-allowed' ) );
+ return;
+ } elseif ( $topicTitle->getRevisionId()->getHex() !==
$this->submitted['prev_revision'] ) {
+ // This is a reasonably effective way to ensure
prev revision matches, but for guarantees against race
+ // conditions there also exists a unique index
on rev_prev_revision in mysql, meaning if someone else inserts against the
+ // parent we and the submitter think is the
latest, our insert will fail.
+ // TODO: Catch whatever exception happens
there, make sure the most recent revision is the one in the cache before
+ // handing user back to specific dialog
indicating race condition
+ $this->addError(
+ 'prev_revision',
+ wfMessage(
'flow-error-prev-revision-mismatch' )->params(
$this->submitted['prev_revision'], $topicTitle->getRevisionId()->getHex() ),
+ array( 'revision_id' =>
$topicTitle->getRevisionId()->getHex() ) // save current revision ID
+ );
+ return;
+ }
}
$this->newRevision = $topicTitle->newNextRevision( $this->user,
$this->submitted['content'], 'edit-title' );
@@ -174,6 +190,7 @@
return; // loadRequestedPost adds its own errors
} elseif ( !$this->permissions->isAllowed( $post, 'reply' ) ) {
$this->addError( 'permissions', wfMessage(
'flow-error-not-allowed' ) );
+ return;
} else {
$this->newRevision = $post->reply( $this->user,
$this->submitted['content'] );
@@ -293,9 +310,11 @@
if ( empty( $this->submitted['postId'] ) ) {
$this->addError( 'post', wfMessage(
'flow-error-missing-postId' ) );
return;
- }
- if ( empty( $this->submitted['content'] ) ) {
+ } elseif ( empty( $this->submitted['content'] ) ) {
$this->addError( 'content', wfMessage(
'flow-error-missing-content' ) );
+ return;
+ } elseif ( empty( $this->submitted['prev_revision'] ) ) {
+ $this->addError( 'prev_revision', wfMessage(
'flow-error-missing-prev-revision-identifier' ) );
return;
}
$post = $this->loadRequestedPost( $this->submitted['postId'] );
@@ -304,6 +323,18 @@
}
if ( !$this->permissions->isAllowed( $post, 'edit-post' ) ) {
$this->addError( 'permissions', wfMessage(
'flow-error-not-allowed' ) );
+ return;
+ } elseif ( $post->getRevisionId()->getHex() !==
$this->submitted['prev_revision'] ) {
+ // This is a reasonably effective way to ensure prev
revision matches, but for guarantees against race
+ // conditions there also exists a unique index on
rev_prev_revision in mysql, meaning if someone else inserts against the
+ // parent we and the submitter think is the latest, our
insert will fail.
+ // TODO: Catch whatever exception happens there, make
sure the most recent revision is the one in the cache before
+ // handing user back to specific dialog indicating race
condition
+ $this->addError(
+ 'prev_revision',
+ wfMessage( 'flow-error-prev-revision-mismatch'
)->params( $this->submitted['prev_revision'], $post->getRevisionId()->getHex()
),
+ array( 'revision_id' =>
$post->getRevisionId()->getHex() ) // save current revision ID
+ );
return;
}
@@ -471,7 +502,7 @@
return $prefix . $templating->render(
"flow:edit-title.html.php", array(
'block' => $this,
'topic' => $this->workflow,
- 'topicTitle' => $topicTitle,
+ 'topicTitle' => $this->newRevision ?:
$topicTitle, // if already submitted, use submitted revision,
), $return );
case 'compare-revisions':
@@ -638,7 +669,7 @@
return $templating->render( "flow:edit-post.html.php", array(
'block' => $this,
'topic' => $this->workflow,
- 'post' => $post,
+ 'post' => $this->newRevision ?: $post, // if already
submitted, use submitted revision
), $return );
}
@@ -727,6 +758,7 @@
$output = array();
$output['post-id'] = $post->getPostId()->getHex();
+ $output['revision-id'] = $post->getRevisionId()->getHex();
$contentFormat = $post->getContentFormat();
// This may force a round trip through parsoid for the wikitext
when
diff --git a/modules/base/action.js b/modules/base/action.js
index 7743206..8c29ed8 100644
--- a/modules/base/action.js
+++ b/modules/base/action.js
@@ -15,4 +15,44 @@
mw.flow.action.prototype.showError = function ( error, errorData ) {
$( this.topic.$container ).flow( 'showError', arguments );
};
+
+ /**
+ * Adds tipsy to an element, with the given text.
+ *
+ * @param {jQuery} $element
+ * @param {string} text
+ */
+ mw.flow.action.prototype.tipsy = function ( $element, text ) {
+ $element
+ .click( function () {
+ $( this ).tipsy( 'hide' );
+ } )
+ .tipsy( {
+ fade: true,
+ gravity: 'w',
+ html: true,
+ trigger: 'manual',
+ className: 'flow-tipsy-destructive',
+ title: function () {
+ /*
+ * I'd prefer to only return content
here, instead of wrapping
+ * it in a div. But we need to add some
padding inside the tipsy.
+ * Tipsy has an option "className",
which we could use to target
+ * the element though CSS, but that
className is only applied
+ * _after_ tipsy has calculated
position, so it's positioning
+ * would then be incorrect.
+ * Tossing in the content inside
another div (which does have a
+ * class to target) works around this
problem.
+ *
+ * @see
https://gerrit.wikimedia.org/r/#/c/103531/
+ */
+
+ // .html() only returns inner html, so
attach the node to a new
+ // parent & grab the full html there
+ var $warning = $( '<div
class="flow-tipsy-noflyout">' ).text( text );
+ return $( '<div>' ).append( $warning
).html();
+ }
+ } )
+ .tipsy( 'show' );
+ };
} ( jQuery, mediaWiki ) );
diff --git a/modules/base/ext.flow.base.js b/modules/base/ext.flow.base.js
index e019ff3..f4656db 100644
--- a/modules/base/ext.flow.base.js
+++ b/modules/base/ext.flow.base.js
@@ -244,7 +244,8 @@
mw.flow.api.changeTitle = mw.flow.api.generateTopicAction(
'edit-title',
[
- 'content'
+ 'content',
+ 'prev_revision'
]
);
@@ -256,7 +257,8 @@
'edit-post',
[
'postId',
- 'content'
+ 'content',
+ 'prev_revision'
]
);
diff --git a/modules/base/styles/actionbox.less
b/modules/base/styles/actionbox.less
index ddb7944..e2f0a45 100644
--- a/modules/base/styles/actionbox.less
+++ b/modules/base/styles/actionbox.less
@@ -93,6 +93,10 @@
border: none;
}
+ .flow-tipsy-noflyout {
+ padding: 10px 22px;
+ }
+
// overwrite tipsy arrow
.tipsy-arrow {
// overwrite core bg image
diff --git a/modules/base/ui-functions.js b/modules/base/ui-functions.js
index 818405f..653fc74 100644
--- a/modules/base/ui-functions.js
+++ b/modules/base/ui-functions.js
@@ -85,7 +85,7 @@
* An object, with the keys 'content' and 'format'. Or
a plain string of wikitext.
* @param {function} submitFunction Function to
call in order to submit the form.
* One parameter, the content.
- * @param {function} loadFunction Function to
call once the form is loaded.
+ * @param {function} loadFunction Function to
call once the form is loaded.
* @return {Promise} A promise
that will be resolved or rejected
* when the form submission has returned.
*/
diff --git a/modules/discussion/post.js b/modules/discussion/post.js
index a74f888..ecd5fae 100644
--- a/modules/discussion/post.js
+++ b/modules/discussion/post.js
@@ -166,7 +166,7 @@
);
deferred.done( $.proxy( this.render, this ) );
-// deferred.fail( $.proxy( this.conflict, this, deferred ) ); //
@todo: not yet implemented
+ deferred.fail( $.proxy( this.conflict, this, deferred, data ) );
return deferred;
};
@@ -186,6 +186,65 @@
};
/**
+ * Called when submitFunction failed.
+ *
+ * @param {jQuery.Deferred} deferred
+ * @param {object} data Old (invalid) this.prepareResult return value
+ * @param {string} error
+ * @param {object} errorData
+ */
+ mw.flow.action.post.edit.prototype.conflict = function ( deferred,
data, error, errorData ) {
+ if (
+ error === 'block-errors' &&
+ errorData.topic && errorData.topic.prev_revision &&
+ errorData.topic.prev_revision.extra &&
errorData.topic.prev_revision.extra.revision_id
+ ) {
+ var $textarea = this.post.$container.find( 'textarea' );
+
+ /*
+ * Overwrite data revision & content.
+ * We'll use raw editor content & editor format to
avoid having
+ * to parse it.
+ */
+ data.content = mw.flow.editor.getRawContent( $textarea
);
+ data.format = mw.flow.editor.getFormat( $textarea );
+ data.revision =
errorData.topic.prev_revision.extra.revision_id;
+
+ /*
+ * At this point, we're still in the deferred's reject
callbacks.
+ * Only after these are completed, is the spinner
removed and the
+ * error message added.
+ * I'm adding another fail-callback, which will be
executed after
+ * the fail has been handled. Only then, we can
properly clean up.
+ */
+ deferred.fail( $.proxy( function ( data, error,
errorData ) {
+ /*
+ * Tipsy will be positioned at the element
where it's bound
+ * to, at the time it's asked to show. It won't
reposition
+ * if the element moves. Since we re-launch the
form, there
+ * may be some movement, so let's have this as
callback when
+ * the form has completed loading before doing
these changes.
+ */
+ var formLoaded = $.proxy( function () {
+ var $button =
this.post.$container.find( '.flow-edit-post-submit' );
+ $button.val( mw.msg(
'flow-edit-post-submit-overwrite' ) );
+ this.tipsy( $button,
errorData.topic.prev_revision.message );
+
+ /*
+ * Trigger keyup in editor, to trick
setupEmptyDisabler
+ * into believing we've made a change &
enable submit.
+ */
+ this.post.$container.find( 'textarea'
).keyup();
+ }, this, data, error, errorData );
+
+ // kill form & error message & re-launch edit
form
+ this.post.$container.find( 'form, .flow-error'
).remove();
+ this.setupEditForm( data, formLoaded );
+ }, this, data, error, errorData ) );
+ }
+ };
+
+ /**
* Display an error if something when wrong.
*
* @param {string} error
diff --git a/modules/discussion/topic.js b/modules/discussion/topic.js
index 91623a8..742303d 100644
--- a/modules/discussion/topic.js
+++ b/modules/discussion/topic.js
@@ -171,7 +171,7 @@
);
deferred.done( $.proxy( this.render, this ) );
-// deferred.fail( $.proxy( this.conflict, this, deferred ) ); //
@todo: not yet implemented
+ deferred.fail( $.proxy( this.conflict, this, deferred, data ) );
return deferred;
};
@@ -187,6 +187,65 @@
};
/**
+ * Called when submitFunction failed.
+ *
+ * @param {jQuery.Deferred} deferred
+ * @param {object} data Old (invalid) this.prepareResult return value
+ * @param {string} error
+ * @param {object} errorData
+ */
+ mw.flow.action.topic.edit.prototype.conflict = function ( deferred,
data, error, errorData ) {
+ if (
+ error === 'block-errors' &&
+ errorData.topic && errorData.topic.prev_revision &&
+ errorData.topic.prev_revision.extra &&
errorData.topic.prev_revision.extra.revision_id
+ ) {
+ var $input = this.topic.$container.find( 'input' );
+
+ /*
+ * Overwrite data revision & content.
+ * We'll use raw editor content & editor format to
avoid having
+ * to parse it.
+ */
+ data.content = $input.val();
+ data.format = 'wikitext';
+ data.revision =
errorData.topic.prev_revision.extra.revision_id;
+
+ /*
+ * At this point, we're still in the deferred's reject
callbacks.
+ * Only after these are completed, is the spinner
removed and the
+ * error message added.
+ * I'm adding another fail-callback, which will be
executed after
+ * the fail has been handled. Only then, we can
properly clean up.
+ */
+ deferred.fail( $.proxy( function ( data, error,
errorData ) {
+ /*
+ * Tipsy will be positioned at the element
where it's bound
+ * to, at the time it's asked to show. It won't
reposition
+ * if the element moves. Since we re-launch the
form, there
+ * may be some movement, so let's have this as
callback when
+ * the form has completed loading before doing
these changes.
+ */
+ var formLoaded = $.proxy( function () {
+ var $button =
this.topic.$container.find( '.flow-edit-title-submit' );
+ $button.val( mw.msg(
'flow-edit-title-submit-overwrite' ) );
+ this.tipsy( $button,
errorData.topic.prev_revision.message );
+
+ /*
+ * Trigger keyup in editor, to trick
setupEmptyDisabler
+ * into believing we've made a change &
enable submit.
+ */
+ this.topic.$container.find( 'input'
).keyup();
+ }, this, data, error, errorData );
+
+ // kill form & error message & re-launch edit
form
+ this.topic.$container.find( 'form, flow-error'
).remove();
+ this.setupEditForm( data, formLoaded );
+ }, this, data, error, errorData ) );
+ }
+ };
+
+ /**
* Parameter supplier (to submitFunction) for flow( 'setupFormHandler'
).
*
* @return {array}
diff --git a/modules/header/forms.js b/modules/header/forms.js
index 353c31c..f80fb8e 100644
--- a/modules/header/forms.js
+++ b/modules/header/forms.js
@@ -157,8 +157,7 @@
data.revision
);
- deferred.done( $.proxy( this.render, this ) );
-// deferred.fail( $.proxy( this.conflict, this, deferred ) ); //
@todo: not yet implemented
+ deferred.fail( $.proxy( this.conflict, this, deferred, data ) );
return deferred;
};
@@ -177,6 +176,65 @@
};
/**
+ * Called when submitFunction failed.
+ *
+ * @param {jQuery.Deferred} deferred
+ * @param {object} data Old (invalid) this.prepareResult return value
+ * @param {string} error
+ * @param {object} errorData
+ */
+ mw.flow.action.header.edit.prototype.conflict = function ( deferred,
data, error, errorData ) {
+ if (
+ error === 'block-errors' &&
+ errorData.header && errorData.header.prev_revision &&
+ errorData.header.prev_revision.extra &&
errorData.header.prev_revision.extra.revision_id
+ ) {
+ var $textarea = this.header.$container.find( 'textarea'
);
+
+ /*
+ * Overwrite data revision & content.
+ * We'll use raw editor content & editor format to
avoid having
+ * to parse it.
+ */
+ data.content = mw.flow.editor.getRawContent( $textarea
);
+ data.format = mw.flow.editor.getFormat( $textarea );
+ data.revision =
errorData.header.prev_revision.extra.revision_id;
+
+ /*
+ * At this point, we're still in the deferred's reject
callbacks.
+ * Only after these are completed, is the spinner
removed and the
+ * error message added.
+ * I'm adding another fail-callback, which will be
executed after
+ * the fail has been handled. Only then, we can
properly clean up.
+ */
+ deferred.fail( $.proxy( function ( data, error,
errorData ) {
+ /*
+ * Tipsy will be positioned at the element
where it's bound
+ * to, at the time it's asked to show. It won't
reposition
+ * if the element moves. Since we re-launch the
form, there
+ * may be some movement, so let's have this as
callback when
+ * the form has completed loading before doing
these changes.
+ */
+ var formLoaded = $.proxy( function () {
+ var $button =
this.header.$container.find( '.flow-edit-header-submit' );
+ $button.val( mw.msg(
'flow-edit-header-submit-overwrite' ) );
+ this.tipsy( $button,
errorData.header.prev_revision.message );
+
+ /*
+ * Trigger keyup in editor, to trick
setupEmptyDisabler
+ * into believing we've made a change &
enable submit.
+ */
+ this.header.$container.find( 'textarea'
).keyup();
+ }, this, data, error, errorData );
+
+ // kill form & error message & re-launch edit
form
+ this.header.$container.find( 'form, flow-error'
).remove();
+ this.setupEditForm( data, formLoaded );
+ }, this, data, error, errorData ) );
+ }
+ };
+
+ /**
* Display an error if something when wrong.
*
* @param {string} error
diff --git a/templates/edit-header.html.php b/templates/edit-header.html.php
index 636b38f..800d08c 100644
--- a/templates/edit-header.html.php
+++ b/templates/edit-header.html.php
@@ -1,5 +1,21 @@
<?php
+$revisionId = '';
+if ( $header ) {
+ // if header already exists, propagate it's revisions id
+ $revisionId = $header->getRevisionId()->getHex();
+
+ /*
+ * If we tried to submit a change against a revision that is not the
latest,
+ * $header will be our own change; let's get the real revision id from
the
+ * error details.
+ */
+ if ( $block->hasErrors( 'prev_revision' ) ) {
+ $error = $block->getErrorExtra( 'prev_revision' );
+ $revisionId = $error['revision_id'];
+ }
+}
+
// owning workflow
echo Html::openElement( 'div', array(
'id' => 'flow-header',
@@ -20,12 +36,17 @@
echo '</ul>';
}
-echo Html::element( 'input', array( 'type' => 'hidden', 'name' =>
'wpEditToken', 'value' => $editToken) );
+echo Html::element( 'input', array(
+ 'type' => 'hidden',
+ 'name' => 'wpEditToken',
+ 'value' => $editToken
+) );
+
if ( $header ) {
echo Html::element( 'input', array(
'type' => 'hidden',
'name' => $block->getName()."[prev_revision]",
- 'value' => $header->getRevisionId()->getHex(),
+ 'value' => $revisionId
) );
}
@@ -35,7 +56,7 @@
array(
'class' => 'mw-ui-input',
'rows' => '10',
- 'data-header-id' => $header ?
$header->getRevisionId()->getHex() : ''
+ 'data-header-id' => $revisionId
)
);
echo Html::openElement( 'div', array(
@@ -44,12 +65,21 @@
echo Html::rawElement( 'div', array(
'class' => 'flow-terms-of-use plainlinks',
), wfMessage( 'flow-terms-of-use-new-topic' )->parse() );
+
+// submit button text will be different if there's a more recent change already
+$submitMessage = 'flow-edit-header-submit';
+$submitClass = 'mw-ui-button mw-ui-constructive';
+if ( $block->hasErrors( 'prev_revision' ) ) {
+ $submitMessage = 'flow-edit-header-submit-overwrite';
+ $submitClass = 'mw-ui-button mw-ui-destructive';
+}
echo Html::element( 'input', array(
'type' => 'submit',
- 'class' => 'mw-ui-button mw-ui-constructive',
- 'value' => wfMessage( 'flow-edit-header-submit' )->plain(),
+ 'class' => $submitClass,
+ 'value' => wfMessage( $submitMessage )->plain(),
) );
echo Html::element( 'div', array( 'class' => 'clear' ) );
+
echo Html::closeElement( 'div' );
echo Html::closeElement( 'form' );
echo Html::closeElement( 'div' );
diff --git a/templates/edit-post.html.php b/templates/edit-post.html.php
index af49e6f..9b85301 100644
--- a/templates/edit-post.html.php
+++ b/templates/edit-post.html.php
@@ -1,5 +1,25 @@
<?php
+$revisionId = $post->getRevisionId()->getHex();
+
+/*
+ * If we tried to submit a change against a revision that is not the latest,
+ * $header will be our own change; let's get the real revision id from the
+ * error details.
+ */
+if ( $block->hasErrors( 'prev_revision' ) ) {
+ $error = $block->getErrorExtra( 'prev_revision' );
+ $revisionId = $error['revision_id'];
+}
+
+// submit button text will be different if there's a more recent change already
+$submitMessage = 'flow-edit-post-submit';
+$submitClass = 'mw-ui-button mw-ui-constructive';
+if ( $block->hasErrors( 'prev_revision' ) ) {
+ $submitMessage = 'flow-edit-post-submit-overwrite';
+ $submitClass = 'mw-ui-button mw-ui-destructive';
+}
+
echo Html::openElement( 'div', array(
'class' => 'flow-topic-container flow-topic-full'
) );
@@ -31,6 +51,11 @@
'name' => $block->getName() . '[postId]',
'value' => $post->getPostId()->getHex(),
) ),
+ Html::element( 'input', array(
+ 'type' => 'hidden',
+ 'name' => $block->getName() . '[prev_revision]',
+ 'value' => $revisionId
+ ) ),
Html::textarea(
$block->getName() . '[content]',
$this->getContent( $post, 'wikitext' ),
@@ -47,8 +72,8 @@
), wfMessage( 'flow-terms-of-use-edit' )->parse() ),
Html::element( 'input', array(
'type' => 'submit',
- 'class' => 'mw-ui-button mw-ui-constructive',
- 'value' => wfMessage( 'flow-edit-post-submit' )->plain()
+ 'class' => $submitClass,
+ 'value' => wfMessage( $submitMessage )->plain()
) ),
Html::element( 'div', array( 'class' => 'clear' ) ),
Html::closeElement( 'div' ),
diff --git a/templates/edit-title.html.php b/templates/edit-title.html.php
index a0d89e1..62df7f8 100644
--- a/templates/edit-title.html.php
+++ b/templates/edit-title.html.php
@@ -1,5 +1,25 @@
<?php
+$revisionId = $topicTitle->getRevisionId()->getHex();
+
+/*
+ * If we tried to submit a change against a revision that is not the latest,
+ * $header will be our own change; let's get the real revision id from the
+ * error details.
+ */
+if ( $block->hasErrors( 'prev_revision' ) ) {
+ $error = $block->getErrorExtra( 'prev_revision' );
+ $revisionId = $error['revision_id'];
+}
+
+// submit button text will be different if there's a more recent change already
+$submitMessage = 'flow-edit-title-submit';
+$submitClass = 'mw-ui-button mw-ui-constructive';
+if ( $block->hasErrors( 'prev_revision' ) ) {
+ $submitMessage = 'flow-edit-title-submit-overwrite';
+ $submitClass = 'mw-ui-button mw-ui-destructive';
+}
+
echo Html::openElement( 'div', array(
'class' => 'flow-topic-container flow-topic-full'
) );
@@ -20,6 +40,11 @@
}
echo Html::element( 'input', array( 'type' => 'hidden', 'name' =>
'wpEditToken', 'value' => $editToken ) ),
+ Html::element( 'input', array(
+ 'type' => 'hidden',
+ 'name' => $block->getName() . '[prev_revision]',
+ 'value' => $revisionId
+ ) ),
Html::element(
'input',
array(
@@ -38,8 +63,8 @@
Html::element( 'input',
array(
'type' => 'submit',
- 'value' => wfMessage( 'flow-edit-title-submit'
)->plain(),
- 'class' => 'mw-ui-button mw-ui-constructive',
+ 'class' => $submitClass,
+ 'value' => wfMessage( $submitMessage )->plain(),
)
),
Html::element( 'div', array( 'class' => 'clear' ) ),
--
To view, visit https://gerrit.wikimedia.org/r/98836
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I70fc7384eb0fb9929db0ad478dc624a22f7fe6a5
Gerrit-PatchSet: 21
Gerrit-Project: mediawiki/extensions/Flow
Gerrit-Branch: master
Gerrit-Owner: Matthias Mullie <[email protected]>
Gerrit-Reviewer: EBernhardson <[email protected]>
Gerrit-Reviewer: Matthias Mullie <[email protected]>
Gerrit-Reviewer: SG <[email protected]>
Gerrit-Reviewer: Siebrand <[email protected]>
Gerrit-Reviewer: Werdna <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits