MediaWiki master
TextConflictHelper.php
Go to the documentation of this file.
1<?php
21namespace MediaWiki\EditPage;
22
23use Content;
33
41
45 protected $title;
46
51
56
60 protected $out;
61
65 protected $stats;
66
70 protected $submitLabel;
71
75 protected $yourtext = '';
76
80 protected $storedversion = '';
81
85 private $contentHandlerFactory;
86
96 public function __construct(
98 IContentHandlerFactory $contentHandlerFactory
99 ) {
100 $this->title = $title;
101 $this->out = $out;
102 $this->stats = $stats;
103 $this->submitLabel = $submitLabel;
104 $this->contentModel = $title->getContentModel();
105 $this->contentHandlerFactory = $contentHandlerFactory;
106
107 $this->contentFormat = $this->contentHandlerFactory
108 ->getContentHandler( $this->contentModel )
109 ->getDefaultFormat();
110 }
111
117 $this->yourtext = $yourtext;
118 $this->storedversion = $storedversion;
119 }
120
124 public function setContentModel( $contentModel ) {
125 $this->contentModel = $contentModel;
126 }
127
131 public function setContentFormat( $contentFormat ) {
132 $this->contentFormat = $contentFormat;
133 }
134
139 public function incrementConflictStats( User $user = null ) {
140 $namespace = 'n/a';
141 $userBucket = 'n/a';
142 $statsdMetrics = [ 'edit.failures.conflict' ];
143
144 // Only include 'standard' namespaces to avoid creating unknown numbers of statsd metrics
145 if (
146 $this->title->getNamespace() >= NS_MAIN &&
147 $this->title->getNamespace() <= NS_CATEGORY_TALK
148 ) {
149 // getNsText() returns empty string if getNamespace() === NS_MAIN
150 $namespace = $this->title->getNsText() ?: 'Main';
151 $statsdMetrics[] = 'edit.failures.conflict.byNamespaceId.' . $this->title->getNamespace();
152 }
153 if ( $user ) {
154 $userBucket = $this->getUserBucket( $user->getEditCount() );
155 $statsdMetrics[] = 'edit.failures.conflict.byUserEdits.' . $userBucket;
156 }
157 if ( $this->stats instanceof StatsFactory ) {
158 $this->stats->getCounter( 'edit_failure_total' )
159 ->setLabel( 'cause', 'conflict' )
160 ->setLabel( 'namespace', $namespace )
161 ->setLabel( 'user_bucket', $userBucket )
162 ->copyToStatsdAt( $statsdMetrics )
163 ->increment();
164 }
165
166 if ( $this->stats instanceof IBufferingStatsdDataFactory ) {
167 foreach ( $statsdMetrics as $metric ) {
168 $this->stats->increment( $metric );
169 }
170 }
171 }
172
177 public function incrementResolvedStats( User $user = null ) {
178 $namespace = 'n/a';
179 $userBucket = 'n/a';
180 $statsdMetrics = [ 'edit.failures.conflict.resolved' ];
181
182 // Only include 'standard' namespaces to avoid creating unknown numbers of statsd metrics
183 if (
184 $this->title->getNamespace() >= NS_MAIN &&
185 $this->title->getNamespace() <= NS_CATEGORY_TALK
186 ) {
187 // getNsText() returns empty string if getNamespace() === NS_MAIN
188 $namespace = $this->title->getNsText() ?: 'Main';
189 $statsdMetrics[] = 'edit.failures.conflict.resolved.byNamespaceId.' . $this->title->getNamespace();
190 }
191
192 if ( $user ) {
193 $userBucket = $this->getUserBucket( $user->getEditCount() );
194 $statsdMetrics[] = 'edit.failures.conflict.resolved.byUserEdits.' . $userBucket;
195 }
196
197 if ( $this->stats instanceof StatsFactory ) {
198 $this->stats->getCounter( 'edit_failure_resolved_total' )
199 ->setLabel( 'cause', 'conflict' )
200 ->setLabel( 'namespace', $namespace )
201 ->setLabel( 'user_bucket', $userBucket )
202 ->copyToStatsdAt( $statsdMetrics )
203 ->increment();
204 }
205
206 if ( $this->stats instanceof IBufferingStatsdDataFactory ) {
207 foreach ( $statsdMetrics as $metric ) {
208 $this->stats->increment( $metric );
209 }
210 }
211 }
212
222 protected function incrementStatsByUserEdits( $userEdits, $keyPrefixBase ) {
223 if ( $this->stats instanceof IBufferingStatsdDataFactory ) {
224 $this->stats->increment( $keyPrefixBase . '.byUserEdits.' . $this->getUserBucket( $userEdits ) );
225 }
226 }
227
232 protected function getUserBucket( ?int $userEdits ): string {
233 if ( $userEdits === null ) {
234 return 'anon';
235 } elseif ( $userEdits > 200 ) {
236 return 'over200';
237 } elseif ( $userEdits > 100 ) {
238 return 'over100';
239 } elseif ( $userEdits > 10 ) {
240 return 'over10';
241 } else {
242 return 'under11';
243 }
244 }
245
249 public function getExplainHeader() {
250 return Html::rawElement(
251 'div',
252 [ 'class' => 'mw-explainconflict' ],
253 $this->out->msg( 'explainconflict', $this->out->msg( $this->submitLabel )->text() )->parse()
254 );
255 }
256
263 public function getEditConflictMainTextBox( array $customAttribs = [] ) {
264 $builder = new TextboxBuilder();
265 $classes = $builder->getTextboxProtectionCSSClasses( $this->title );
266
267 $attribs = [
268 'aria-label' => $this->out->msg( 'edit-textarea-aria-label' )->text(),
269 'tabindex' => 1,
270 ];
271 $attribs += $customAttribs;
272
273 $attribs = $builder->mergeClassesIntoAttributes( $classes, $attribs );
274
275 $attribs = $builder->buildTextboxAttribs(
276 'wpTextbox1',
277 $attribs,
278 $this->out->getUser(),
279 $this->title
280 );
281
282 return Html::textarea(
283 'wpTextbox1',
284 $builder->addNewLineAtEnd( $this->storedversion ),
285 $attribs
286 );
287 }
288
296 return '';
297 }
298
305 public function getEditFormHtmlAfterContent() {
306 return '';
307 }
308
314 $this->out->wrapWikiMsg( '<h2>$1</h2>', "yourdiff" );
315
316 $yourContent = $this->toEditContent( $this->yourtext );
317 $storedContent = $this->toEditContent( $this->storedversion );
318 $handler = $this->contentHandlerFactory->getContentHandler( $this->contentModel );
319 $diffEngine = $handler->createDifferenceEngine( $this->out );
320
321 $diffEngine->setContent( $yourContent, $storedContent );
322 $diffEngine->showDiff(
323 $this->out->msg( 'yourtext' )->parse(),
324 $this->out->msg( 'storedversion' )->text()
325 );
326
327 $this->out->wrapWikiMsg( '<h2>$1</h2>', "yourtext" );
328
329 $builder = new TextboxBuilder();
330 $attribs = $builder->buildTextboxAttribs(
331 'wpTextbox2',
332 [ 'tabindex' => 6, 'readonly' ],
333 $this->out->getUser(),
334 $this->title
335 );
336
337 $this->out->addHTML(
338 Html::textarea( 'wpTextbox2', $builder->addNewLineAtEnd( $this->yourtext ), $attribs )
339 );
340 }
341
346 private function toEditContent( $text ) {
347 return ContentHandler::makeContent(
348 $text,
349 $this->title,
350 $this->contentModel,
351 $this->contentFormat
352 );
353 }
354}
const NS_MAIN
Definition Defines.php:65
const NS_CATEGORY_TALK
Definition Defines.php:80
if(!defined('MW_SETUP_CALLBACK'))
Definition WebStart.php:81
A content handler knows how do deal with a specific type of content on a wiki page.
Exception thrown when an unregistered content model is requested.
Helper for displaying edit conflicts in text content models to users.
incrementResolvedStats(User $user=null)
Record when a user has resolved an edit conflict.
getEditFormHtmlAfterContent()
Content to go in the edit form after textbox1.
getEditConflictMainTextBox(array $customAttribs=[])
HTML to build the textbox1 on edit conflicts.
showEditFormTextAfterFooters()
Content to go in the edit form after the footers (templates on this page, hidden categories,...
incrementConflictStats(User $user=null)
Record a user encountering an edit conflict.
__construct(Title $title, OutputPage $out, $stats, $submitLabel, IContentHandlerFactory $contentHandlerFactory)
IBufferingStatsdDataFactory StatsFactory $stats
setTextboxes( $yourtext, $storedversion)
incrementStatsByUserEdits( $userEdits, $keyPrefixBase)
Retained temporarily for backwards-compatibility.
string $submitLabel
Message key for submit button's label.
getEditFormHtmlBeforeContent()
Content to go in the edit form before textbox1.
Helps EditPage build textboxes.
This class is a collection of static functions that serve two purposes:
Definition Html.php:56
This is one of the Core classes and should be read at least once by any new developers.
Represents a title within MediaWiki.
Definition Title.php:79
getContentModel( $flags=0)
Get the page's content model id, see the CONTENT_MODEL_XXX constants.
Definition Title.php:1067
internal since 1.36
Definition User.php:94
StatsFactory Implementation.
Base interface for representing page content.
Definition Content.php:37
MediaWiki adaptation of StatsdDataFactory that provides buffering functionality.
getContentHandler(string $modelID)
Returns a ContentHandler instance for the given $modelID.