jenkins-bot has submitted this change and it was merged.

Change subject: Schema:Edit instrumentation
......................................................................


Schema:Edit instrumentation

Depends on Ib8612626

Bug: T88027
Change-Id: I67f1000d23cb257df29d5d4be8ae85764458e6c1
---
M WikiEditor.hooks.php
M WikiEditor.php
A modules/ext.wikiEditor.init.js
M modules/jquery.wikiEditor.js
4 files changed, 277 insertions(+), 1 deletion(-)

Approvals:
  Catrope: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/WikiEditor.hooks.php b/WikiEditor.hooks.php
index 321c959..fca9406 100644
--- a/WikiEditor.hooks.php
+++ b/WikiEditor.hooks.php
@@ -7,6 +7,9 @@
  */
 
 class WikiEditorHooks {
+       // ID used for grouping entries all of a session's entries together in
+       // EventLogging.
+       private static $statsId = false;
 
        /* Protected Static Members */
 
@@ -136,6 +139,48 @@
        }
 
        /**
+        * Log stuff to EventLogging's Schema:Edit - see 
https://meta.wikimedia.org/wiki/Schema:Edit
+        * If you don't have EventLogging installed, does nothing.
+        *
+        * @param string $action
+        * @param Article $article Which article (with full context, page, 
title, etc.)
+        * @param array $data Data to log for this action
+        * @return bool Whether the event was logged or not.
+        */
+       public static function doEventLogging( $action, $article, $data = 
array() ) {
+               global $wgVersion;
+               if ( !class_exists( 'EventLogging' ) ) {
+                       return false;
+               }
+
+               $user = $article->getContext()->getUser();
+               $page = $article->getPage();
+               $title = $article->getTitle();
+
+               $data = array(
+                       'action' => $action,
+                       'version' => 1,
+                       'editor' => 'wikitext',
+                       'platform' => 'desktop', // FIXME
+                       'integration' => 'page',
+                       'page.length' => -1, // FIXME
+                       'page.id' => $page->getId(),
+                       'page.title' => $title->getPrefixedText(),
+                       'page.ns' => $title->getNamespace(),
+                       'page.revid' => $page->getRevision() && 
$page->getRevision()->getId(),
+                       'user.id' => $user->getId(),
+                       'user.editCount' => $user->getEditCount(),
+                       'mediawiki.version' => $wgVersion
+               ) + $data;
+
+               if ( $user->isAnon() ) {
+                       $data['user.class'] = 'IP';
+               }
+
+               return EventLogging::logEvent( 'Edit', 11448630, $data );
+       }
+
+       /**
         * EditPage::showEditForm:initial hook
         *
         * Adds the modules to the edit form
@@ -161,6 +206,66 @@
                                $outputPage->addModules( $feature['modules'] );
                        }
                }
+
+               $article = $editPage->getArticle();
+               $request = $article->getContext()->getRequest();
+               // Don't run this if the request was posted - we don't want to 
log 'init' when the
+               // user just pressed 'Show preview' or 'Show changes', or 
switched from VE keeping
+               // changes.
+               if ( class_exists( 'EventLogging' ) && !$request->wasPosted() ) 
{
+                       $data = array();
+                       $data['editingSessionId'] = self::getEditingStatsId();
+                       if ( $request->getVal( 'section', false ) ) {
+                               $data['action.init.type'] = 'section';
+                       } else {
+                               $data['action.init.type'] = 'page';
+                       }
+                       if ( $request->getHeader( 'Referer' ) ) {
+                               if ( $request->getVal( 'section' ) === 'new' || 
!$article->exists() ) {
+                                       $data['action.init.mechanism'] = 'new';
+                               } else {
+                                       $data['action.init.mechanism'] = 
'click';
+                               }
+                       } else {
+                               $data['action.init.mechanism'] = 'url';
+                       }
+
+                       self::doEventLogging( 'init', $article, $data );
+               }
+
+               return true;
+       }
+
+       /**
+        * EditPage::showEditForm:fields hook
+        *
+        * Adds the event fields to the edit form
+        *
+        * @param EditPage $editPage the current EditPage object.
+        * @param OutputPage $outputPage object.
+        * @return bool
+        */
+       public static function editPageShowEditFormFields( $editPage, 
$outputPage ) {
+               if ( $editPage->contentModel !== CONTENT_MODEL_WIKITEXT ) {
+                       return true;
+               }
+
+               $req = $outputPage->getContext()->getRequest();
+               $editingStatsId = $req->getVal( 'editingStatsId' );
+               if ( !$editingStatsId ) {
+                       $editingStatsId = self::getEditingStatsId();
+               }
+               $outputPage->addHTML(
+                       Xml::element(
+                               'input',
+                               array(
+                                       'type' => 'hidden',
+                                       'name' => 'editingStatsId',
+                                       'id' => 'editingStatsId',
+                                       'value' => $editingStatsId
+                               )
+                       )
+               );
                return true;
        }
 
@@ -296,4 +401,97 @@
                $vars['wgWikiEditorMagicWords'] = $magicWords;
        }
 
+
+       /**
+        * Adds WikiEditor JS to the output.
+        *
+        * This is attached to the MediaWiki 'BeforePageDisplay' hook.
+        *
+        * @param OutputPage $output
+        * @param Skin $skin
+        * @return boolean
+        */
+       public static function onBeforePageDisplay( OutputPage &$output, Skin 
&$skin ) {
+               $output->addModules( array( 'ext.wikiEditor.init' ) );
+               return true;
+       }
+
+       /**
+        * Gets a 32 character alphanumeric random string to be used for stats.
+        * @return string
+        */
+       private static function getEditingStatsId() {
+               if ( self::$statsId ) {
+                       return self::$statsId;
+               }
+               return self::$statsId = MWCryptRand::generateHex( 32 );
+       }
+
+       /**
+        * This is attached to the MediaWiki 'EditPage::attemptSave' hook.
+        *
+        * @param EditPage $editPage
+        * @param Status $status
+        * @return boolean
+        */
+       public static function editPageAttemptSave( EditPage $editPage ) {
+               $article = $editPage->getArticle();
+               $request = $article->getContext()->getRequest();
+               if ( $request->getVal( 'editingStatsId', false ) !== false ) {
+                       self::doEventLogging(
+                               'saveAttempt',
+                               $article,
+                               array( 'editingSessionId' => $request->getVal( 
'editingStatsId' ) )
+                       );
+               }
+
+               return true;
+       }
+
+       /**
+        * This is attached to the MediaWiki 'EditPage::attemptSave:after' hook.
+        *
+        * @param EditPage $editPage
+        * @param Status $status
+        * @return boolean
+        */
+       public static function editPageAttemptSaveAfter( EditPage $editPage, 
Status $status ) {
+               $article = $editPage->getArticle();
+               $request = $article->getContext()->getRequest();
+               if ( $request->getVal( 'editingStatsId', false ) !== false ) {
+                       $data = array();
+                       $data['editingStatsId'] = $request->getVal( 
'editingStatsId' );
+
+                       if ( $status->isOK() ) {
+                               $action = 'saveSuccess';
+                       } else {
+                               $action = 'saveFailure';
+                               $errors = $status->getErrorsArray();
+
+                               if ( isset( $errors[0][0] ) ) {
+                                       $data['action.saveFailure.message'] = 
$errors[0][0];
+                               }
+
+                               if ( $status->value === 
EditPage::AS_CONFLICT_DETECTED ) {
+                                       $data['action.saveFailure.type'] = 
'editConflict';
+                               } else if ( $status->value === 
EditPage::AS_ARTICLE_WAS_DELETED ) {
+                                       $data['action.saveFailure.type'] = 
'editPageDeleted';
+                               } else if ( isset( $errors[0][0] ) && 
$errors[0][0] === 'abusefilter-disallowed' ) {
+                                       $data['action.saveFailure.type'] = 
'extensionAbuseFilter';
+                               } else if ( isset( 
$editPage->getArticle()->getPage()->ConfirmEdit_ActivateCaptcha ) ) {
+                                       // TODO: :(
+                                       $data['action.saveFailure.type'] = 
'extensionCaptcha';
+                               } else if ( isset( $errors[0][0] ) && 
$errors[0][0] === 'spamprotectiontext' ) {
+                                       $data['action.saveFailure.type'] = 
'extensionSpamBlacklist';
+                               } else {
+                                               // Catch everything else... We 
don't seem to get userBadToken or
+                                               // userNewUser through this 
hook.
+                                               
$data['action.saveFailure.type'] = 'responseUnknown';
+                               }
+                       }
+                       self::doEventLogging( $action, $article, $data );
+               }
+
+               return true;
+       }
 }
diff --git a/WikiEditor.php b/WikiEditor.php
index 070a128..de63dc6 100644
--- a/WikiEditor.php
+++ b/WikiEditor.php
@@ -55,6 +55,10 @@
 $GLOBALS['wgHooks']['ResourceLoaderTestModules'][] = 
'WikiEditorHooks::resourceLoaderTestModules';
 $GLOBALS['wgHooks']['MakeGlobalVariablesScript'][] = 
'WikiEditorHooks::makeGlobalVariablesScript';
 $GLOBALS['wgHooks']['EditPageBeforeEditToolbar'][] = 
'WikiEditorHooks::EditPageBeforeEditToolbar';
+$GLOBALS['wgHooks']['EditPage::showEditForm:fields'][] = 
'WikiEditorHooks::editPageShowEditFormFields';
+$GLOBALS['wgHooks']['BeforePageDisplay'][] = 
'WikiEditorHooks::onBeforePageDisplay';
+$GLOBALS['wgHooks']['EditPage::attemptSave'][] = 
'WikiEditorHooks::editPageAttemptSave';
+$GLOBALS['wgHooks']['EditPage::attemptSave:after'][] = 
'WikiEditorHooks::editPageAttemptSaveAfter';
 
 $wikiEditorTpl = array(
        'localBasePath' => __DIR__ . '/modules',
@@ -356,10 +360,16 @@
 
        /* WikiEditor Resources */
 
+       'ext.wikiEditor.init' => $wikiEditorTpl + array(
+               'scripts' => 'ext.wikiEditor.init.js'
+       ),
        'ext.wikiEditor' => $wikiEditorTpl + array(
                'scripts' => 'ext.wikiEditor.js',
                'styles' => 'ext.wikiEditor.less',
-               'dependencies' => 'jquery.wikiEditor',
+               'dependencies' => array(
+                       'ext.wikiEditor.init',
+                       'jquery.wikiEditor'
+               ),
        ),
        'ext.wikiEditor.dialogs' => $wikiEditorTpl + array(
                'scripts' => 'ext.wikiEditor.dialogs.js',
diff --git a/modules/ext.wikiEditor.init.js b/modules/ext.wikiEditor.init.js
new file mode 100644
index 0000000..2ae1a41
--- /dev/null
+++ b/modules/ext.wikiEditor.init.js
@@ -0,0 +1,44 @@
+/*!
+ * WikiEditor extension initialisation
+ * @copyright 2015 Wikimedia Foundation and Alex Monk
+ * @license GPL; see COPYING
+ */
+
+( function ( mw, $ ) {
+       mw.wikiEditor = {
+               logEditEvent: function ( action, data ) {
+                       mw.loader.using( 'schema.Edit' ).done( function () {
+                               data = $.extend( {
+                                       version: 1,
+                                       action: action,
+                                       editor: 'wikitext',
+                                       platform: 'desktop', // FIXME
+                                       integration: 'page',
+                                       'page.id': mw.config.get( 'wgArticleId' 
),
+                                       'page.title': mw.config.get( 
'wgPageName' ),
+                                       'page.ns': mw.config.get( 
'wgNamespaceNumber' ),
+                                       'page.revid': mw.config.get( 
'wgRevisionId' ),
+                                       'page.length': -1, // FIXME
+                                       'user.id': mw.user.getId(),
+                                       'user.editCount': mw.config.get( 
'wgUserEditCount', 0 ),
+                                       'mediawiki.version': mw.config.get( 
'wgVersion' )
+                               }, data );
+
+                               if ( mw.user.isAnon() ) {
+                                       data['user.class'] = 'IP';
+                               }
+
+                               data['action.' + action + '.type'] = data.type;
+                               data['action.' + action + '.mechanism'] = 
data.mechanism;
+                               data['action.' + action + '.timing'] = 
data.timing === undefined ?
+                                       0 : Math.floor( data.timing );
+                               // Remove renamed properties
+                               delete data.type;
+                               delete data.mechanism;
+                               delete data.timing;
+
+                               mw.eventLog.logEvent( 'Edit', data );
+                       } );
+               }
+       };
+}( mediaWiki, jQuery ) );
diff --git a/modules/jquery.wikiEditor.js b/modules/jquery.wikiEditor.js
index 6a8d1db..b68b523 100644
--- a/modules/jquery.wikiEditor.js
+++ b/modules/jquery.wikiEditor.js
@@ -549,6 +549,30 @@
        $( window ).resize( function ( event ) {
                context.fn.trigger( 'resize', event );
        } );
+
+       mw.wikiEditor.logEditEvent( 'ready', {
+               editingSessionId: $( '#editform input#editingStatsId' ).val()
+       } );
+       $( '#editform' ).submit( function () {
+               context.submitting = true;
+       } );
+       this.onUnloadFallback = window.onunload;
+       window.onunload = function () {
+               var fallbackResult;
+
+               if ( this.onUnloadFallback ) {
+                       fallbackResult = this.onUnloadFallback();
+               }
+
+               if ( !context.submitting ) {
+                       mw.wikiEditor.logEditEvent( 'abort', {
+                               editingSessionId: $( '#editform 
input#editingStatsId' ).val(),
+                               // TODO: abort.type
+                       } );
+               }
+
+               return fallbackResult;
+       };
 }
 
 /* API Execution */

-- 
To view, visit https://gerrit.wikimedia.org/r/191221
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I67f1000d23cb257df29d5d4be8ae85764458e6c1
Gerrit-PatchSet: 17
Gerrit-Project: mediawiki/extensions/WikiEditor
Gerrit-Branch: master
Gerrit-Owner: Alex Monk <kren...@gmail.com>
Gerrit-Reviewer: Alex Monk <kren...@gmail.com>
Gerrit-Reviewer: Catrope <roan.katt...@gmail.com>
Gerrit-Reviewer: Jforrester <jforres...@wikimedia.org>
Gerrit-Reviewer: Krinkle <krinklem...@gmail.com>
Gerrit-Reviewer: Nuria <nu...@wikimedia.org>
Gerrit-Reviewer: Ori.livneh <o...@wikimedia.org>
Gerrit-Reviewer: TheDJ <hartman.w...@gmail.com>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to