MediaWiki REL1_34
WikiEditorHooks.php
Go to the documentation of this file.
1<?php
10
12 // ID used for grouping entries all of a session's entries together in
13 // EventLogging.
14 private static $statsId = false;
15
16 /* Static Methods */
17
28 public static function doEventLogging( $action, $article, $data = [] ) {
29 global $wgVersion, $wgWMESchemaEditAttemptStepSamplingRate;
30 $extensionRegistry = ExtensionRegistry::getInstance();
31 if ( !$extensionRegistry->isLoaded( 'EventLogging' ) ) {
32 return false;
33 }
34 // Sample 6.25%
35 $samplingRate = $wgWMESchemaEditAttemptStepSamplingRate ?? 0.0625;
36 $inSample = EventLogging::sessionInSample( 1 / $samplingRate, $data['editing_session_id'] );
37 $shouldOversample = $extensionRegistry->isLoaded( 'WikimediaEvents' ) &&
38 WikimediaEventsHooks::shouldSchemaEditAttemptStepOversample( $article->getContext() );
39 if ( !$inSample && !$shouldOversample ) {
40 return false;
41 }
42
43 $user = $article->getContext()->getUser();
44 $page = $article->getPage();
45 $title = $article->getTitle();
46
47 $data = [
48 'action' => $action,
49 'version' => 1,
50 'is_oversample' => !$inSample,
51 'editor_interface' => 'wikitext',
52 'platform' => 'desktop', // FIXME
53 'integration' => 'page',
54 'page_id' => $page->getId(),
55 'page_title' => $title->getPrefixedText(),
56 'page_ns' => $title->getNamespace(),
57 'revision_id' => $page->getRevision() ? $page->getRevision()->getId() : 0,
58 'user_id' => $user->getId(),
59 'user_editcount' => $user->getEditCount() ?: 0,
60 'mw_version' => $wgVersion,
61 ] + $data;
62
63 if ( $user->isAnon() ) {
64 $data['user_class'] = 'IP';
65 }
66
67 return EventLogging::logEvent( 'EditAttemptStep', 18530416, $data );
68 }
69
78 public static function editPageShowEditFormInitial( EditPage $editPage, OutputPage $outputPage ) {
79 if ( $editPage->contentModel !== CONTENT_MODEL_WIKITEXT ) {
80 return;
81 }
82
83 $article = $editPage->getArticle();
84 $request = $article->getContext()->getRequest();
85
86 // Add modules if enabled
87 $user = $article->getContext()->getUser();
88 if ( $user->getOption( 'usebetatoolbar' ) ) {
89 $outputPage->addModuleStyles( 'ext.wikiEditor.styles' );
90 $outputPage->addModules( 'ext.wikiEditor' );
91 }
92
93 // Don't run this if the request was posted - we don't want to log 'init' when the
94 // user just pressed 'Show preview' or 'Show changes', or switched from VE keeping
95 // changes.
96 if ( ExtensionRegistry::getInstance()->isLoaded( 'EventLogging' ) && !$request->wasPosted() ) {
97 $data = [];
98 $data['editing_session_id'] = self::getEditingStatsId();
99 if ( $request->getVal( 'section' ) ) {
100 $data['init_type'] = 'section';
101 } else {
102 $data['init_type'] = 'page';
103 }
104 if ( $request->getHeader( 'Referer' ) ) {
105 if ( $request->getVal( 'section' ) === 'new' || !$article->exists() ) {
106 $data['init_mechanism'] = 'new';
107 } else {
108 $data['init_mechanism'] = 'click';
109 }
110 } else {
111 $data['init_mechanism'] = 'url';
112 }
113
114 self::doEventLogging( 'init', $article, $data );
115 }
116 }
117
126 public static function editPageShowEditFormFields( EditPage $editPage, OutputPage $outputPage ) {
127 if ( $editPage->contentModel !== CONTENT_MODEL_WIKITEXT ) {
128 return;
129 }
130
131 $req = $outputPage->getRequest();
132 $editingStatsId = $req->getVal( 'editingStatsId' );
133 if ( !$editingStatsId || !$req->wasPosted() ) {
134 $editingStatsId = self::getEditingStatsId();
135 }
136
137 $outputPage->addHTML(
138 Xml::element(
139 'input',
140 [
141 'type' => 'hidden',
142 'name' => 'editingStatsId',
143 'id' => 'editingStatsId',
144 'value' => $editingStatsId
145 ]
146 )
147 );
148 }
149
158 public static function EditPageBeforeEditToolbar( &$toolbar ) {
159 global $wgUser;
160 if ( $wgUser->getOption( 'usebetatoolbar' ) ) {
161 $toolbar = '';
162 // Return false to signify that the toolbar has been over-written, so
163 // the old toolbar code shouldn't be added to the page.
164 return false;
165 }
166 return true;
167 }
168
177 public static function getPreferences( $user, &$defaultPreferences ) {
178 // Ideally this key would be 'wikieditor-toolbar'
179 $defaultPreferences['usebetatoolbar'] = [
180 'type' => 'toggle',
181 'label-message' => 'wikieditor-toolbar-preference',
182 'help-message' => 'wikieditor-toolbar-preference-help',
183 'section' => 'editing/editor',
184 ];
185 }
186
192 public static function getModuleData( ResourceLoaderContext $context, Config $config ) {
193 return [
194 // expose magic words for use by the wikieditor toolbar
195 'magicWords' => self::getMagicWords(),
196 'signature' => self::getSignatureMessage( $context )
197 ];
198 }
199
205 public static function getModuleDataSummary( ResourceLoaderContext $context, Config $config ) {
206 return [
207 'magicWords' => self::getMagicWords(),
208 'signature' => self::getSignatureMessage( $context, true )
209 ];
210 }
211
212 private static function getSignatureMessage( MessageLocalizer $ml, $raw = false ) {
213 $msg = $ml->msg( 'sig-text' )->params( '~~~~' )->inContentLanguage();
214 return $raw ? $msg->plain() : $msg->text();
215 }
216
220 private static function getMagicWords() {
221 $requiredMagicWords = [
222 'redirect',
223 'img_right',
224 'img_left',
225 'img_none',
226 'img_center',
227 'img_thumbnail',
228 'img_framed',
229 'img_frameless',
230 ];
231 $magicWords = [];
232 if ( class_exists( MagicWordFactory::class ) ) {
233 $factory = MediaWikiServices::getInstance()->getMagicWordFactory();
234 }
235 foreach ( $requiredMagicWords as $name ) {
236 if ( class_exists( MagicWordFactory::class ) ) {
237 $magicWords[$name] = $factory->get( $name )->getSynonym( 0 );
238 } else {
239 $magicWords[$name] = MagicWord::get( $name )->getSynonym( 0 );
240 }
241 }
242 return $magicWords;
243 }
244
249 private static function getEditingStatsId() {
250 if ( !self::$statsId ) {
251 self::$statsId = MWCryptRand::generateHex( 32 );
252 }
253 return self::$statsId;
254 }
255
261 public static function editPageAttemptSave( EditPage $editPage ) {
262 $article = $editPage->getArticle();
263 $request = $article->getContext()->getRequest();
264 if ( $request->getVal( 'editingStatsId' ) ) {
266 'saveAttempt',
267 $article,
268 [ 'editing_session_id' => $request->getVal( 'editingStatsId' ) ]
269 );
270 }
271 }
272
279 public static function editPageAttemptSaveAfter( EditPage $editPage, Status $status ) {
280 $article = $editPage->getArticle();
281 $request = $article->getContext()->getRequest();
282 if ( $request->getVal( 'editingStatsId' ) ) {
283 $data = [];
284 $data['editing_session_id'] = $request->getVal( 'editingStatsId' );
285
286 if ( $status->isOK() ) {
287 $action = 'saveSuccess';
288 } else {
289 $action = 'saveFailure';
290 $errors = $status->getErrorsArray();
291
292 if ( isset( $errors[0][0] ) ) {
293 $data['save_failure_message'] = $errors[0][0];
294 }
295
296 if ( $status->value === EditPage::AS_CONFLICT_DETECTED ) {
297 $data['save_failure_type'] = 'editConflict';
298 } elseif ( $status->value === EditPage::AS_ARTICLE_WAS_DELETED ) {
299 $data['save_failure_type'] = 'editPageDeleted';
300 } elseif ( isset( $errors[0][0] ) && $errors[0][0] === 'abusefilter-disallowed' ) {
301 $data['save_failure_type'] = 'extensionAbuseFilter';
302 } elseif ( isset( $editPage->getArticle()->getPage()->ConfirmEdit_ActivateCaptcha ) ) {
303 // TODO: :(
304 $data['save_failure_type'] = 'extensionCaptcha';
305 } elseif ( isset( $errors[0][0] ) && $errors[0][0] === 'spam-blacklisted-link' ) {
306 $data['save_failure_type'] = 'extensionSpamBlacklist';
307 } else {
308 // Catch everything else... We don't seem to get userBadToken or
309 // userNewUser through this hook.
310 $data['save_failure_type'] = 'responseUnknown';
311 }
312 }
313 self::doEventLogging( $action, $article, $data );
314 }
315 }
316}
$wgVersion
MediaWiki version number.
The edit page/HTML interface (split from Article) The actual database and text munging is still in Ar...
Definition EditPage.php:46
const AS_CONFLICT_DETECTED
Status: (non-resolvable) edit conflict.
Definition EditPage.php:122
const AS_ARTICLE_WAS_DELETED
Status: article was deleted while editing and param wpRecreate == false or form was not posted.
Definition EditPage.php:106
static generateHex( $chars)
Generate a run of cryptographically random data and return it in hexadecimal string format.
static get( $id)
Factory: creates an object representing an ID.
MediaWikiServices is the service locator for the application scope of MediaWiki.
This is one of the Core classes and should be read at least once by any new developers.
addModuleStyles( $modules)
Load the styles of one or more ResourceLoader modules on this page.
addHTML( $text)
Append $text to the body HTML.
addModules( $modules)
Load one or more ResourceLoader modules on this page.
Context object that contains information about the state of a specific ResourceLoader web request.
isOK()
Returns whether the operation completed.
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition Status.php:40
getErrorsArray()
Get the list of errors (but not warnings)
Definition Status.php:343
static editPageShowEditFormInitial(EditPage $editPage, OutputPage $outputPage)
EditPage::showEditForm:initial hook.
static getEditingStatsId()
Gets a 32 character alphanumeric random string to be used for stats.
static editPageAttemptSave(EditPage $editPage)
This is attached to the MediaWiki 'EditPage::attemptSave' hook.
static getMagicWords()
Expose useful magic words which are used by the wikieditor toolbar.
static getModuleData(ResourceLoaderContext $context, Config $config)
static getSignatureMessage(MessageLocalizer $ml, $raw=false)
static EditPageBeforeEditToolbar(&$toolbar)
EditPageBeforeEditToolbar hook.
static editPageAttemptSaveAfter(EditPage $editPage, Status $status)
This is attached to the MediaWiki 'EditPage::attemptSave:after' hook.
static getModuleDataSummary(ResourceLoaderContext $context, Config $config)
static getPreferences( $user, &$defaultPreferences)
GetPreferences hook.
static editPageShowEditFormFields(EditPage $editPage, OutputPage $outputPage)
EditPage::showEditForm:fields hook.
static doEventLogging( $action, $article, $data=[])
Log stuff to EventLogging's Schema:EditAttemptStep - see https://meta.wikimedia.org/wiki/Schema:EditA...
const CONTENT_MODEL_WIKITEXT
Definition Defines.php:224
Interface for configuration instances.
Definition Config.php:28
Interface for localizing messages in MediaWiki.
msg( $key,... $params)
This is the method for getting translated interface messages.
$context
Definition load.php:45