Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
5.41% covered (danger)
5.41%
2 / 37
25.00% covered (danger)
25.00%
2 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
AccountCreationLogger
5.41% covered (danger)
5.41%
2 / 37
25.00% covered (danger)
25.00%
2 / 8
113.42
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 logAuthEvent
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
12
 doLogEvent
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
2
 submitEvent
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 logLoginEvent
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 logAccountCreationEvent
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 logPageImpression
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
6
 determineStreamForPage
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace WikimediaEvents;
4
5use MediaWiki\Auth\AuthenticationResponse;
6use MediaWiki\Context\RequestContext;
7use MediaWiki\Extension\EventLogging\EventLogging;
8use MediaWiki\Page\PageReference;
9use MediaWiki\SpecialPage\SpecialPageFactory;
10use MediaWiki\User\UserIdentity;
11use MediaWiki\User\UserIdentityUtils;
12use MediaWiki\WikiMap\WikiMap;
13
14class AccountCreationLogger {
15
16    private const SCHEMA_VERSIONED = '/analytics/mediawiki/accountcreation/account_conversion/1.0.0';
17    private const STREAM_REGISTER = 'mediawiki.accountcreation.account_conversion';
18    private const STREAM_LOGIN = 'mediawiki.accountcreation.login';
19    private SpecialPageFactory $specialPageFactory;
20    /**
21     * @var UserIdentityUtils
22     */
23    private UserIdentityUtils $userIdentityUtils;
24
25    /**
26     * @var array Mapping of special page titles to their corresponding event streams.
27     */
28    private $pageStreamMap = [
29        'CreateAccount' => self::STREAM_REGISTER,
30        'Userlogin' => self::STREAM_LOGIN,
31    ];
32
33    public function __construct( UserIdentityUtils $userIdentityUtils, SpecialPageFactory $specialPageFactory ) {
34        $this->userIdentityUtils = $userIdentityUtils;
35        $this->specialPageFactory = $specialPageFactory;
36    }
37
38    /**
39     * Handles logging of authentication and account creation events.
40     *
41     * @param string $stream The stream event.
42     * @param string $eventType The event type ('success' or 'failure').
43     * @param UserIdentity $performer The user involved in the event.
44     * @param AuthenticationResponse $response The authentication response.
45     */
46    public function logAuthEvent(
47        string $stream, string $eventType, UserIdentity $performer, AuthenticationResponse $response ): void {
48        $additionalData = [];
49        $title = RequestContext::getMain()->getTitle();
50        if ( $title !== null ) {
51            $additionalData += [
52                'page_title' => $title->getDBkey(),
53                'page_namespace' => $title->getNamespace(),
54            ];
55        }
56        if ( $response->status === AuthenticationResponse::FAIL ) {
57            $additionalData['error_message_key'] = $response->message->getKey();
58        }
59        $this->doLogEvent( $stream, $eventType, $performer, $additionalData );
60    }
61
62    /**
63     * Logs different types of events (e.g., impressions, successes, failures)
64     * related to account creation and user login.
65     *
66     * @param string $stream The stream event.
67     * @param string $eventType The type of event (e.g., 'impression', 'success', 'failure').
68     * @param UserIdentity $user The user associated with the event.
69     */
70    private function doLogEvent(
71        string $stream, string $eventType, UserIdentity $user, array $additionalData ): void {
72        $eventData = [
73            '$schema' => self::SCHEMA_VERSIONED,
74            'event_type' => $eventType,
75            'performer' => [
76                'user_id' => $user->getId(),
77                'user_text' => $user->getName(),
78                'is_temp' => $this->userIdentityUtils->isTemp( $user )
79            ],
80            'source_wiki' => WikiMap::getCurrentWikiId()
81        ];
82        $eventData = array_merge( $eventData, $additionalData );
83        $this->submitEvent( $stream, $eventData );
84    }
85
86    /**
87     * Submits the event data to the EventLogging service.
88     *
89     * @param string $stream The event stream.
90     * @param array $eventData The prepared event data.
91     */
92    private function submitEvent( string $stream, array $eventData ): void {
93        EventLogging::submit( $stream, $eventData );
94    }
95
96    /**
97     * Logs login event with a specified event type.
98     * @param string $eventType The type of the login event (e.g., 'success', 'failure').
99     * @param UserIdentity $performer The user who is performing the login action.
100     * @param AuthenticationResponse $response The response received from the authentication process
101     */
102    public function logLoginEvent(
103        string $eventType, UserIdentity $performer, AuthenticationResponse $response ): void {
104        $this->logAuthEvent( self::STREAM_LOGIN, $eventType, $performer, $response );
105    }
106
107    /**
108     * Logs account creation event with a specified event type.
109     * @param string $eventType The type of the account creation event (e.g., 'success', 'failure').
110     * @param UserIdentity $performer The user who is attempting to
111     *        create a new account or the user performing the action.
112     * @param AuthenticationResponse $response The response from the account creation process.
113     */
114    public function logAccountCreationEvent(
115        string $eventType, UserIdentity $performer, AuthenticationResponse $response ): void {
116        $this->logAuthEvent( self::STREAM_REGISTER, $eventType, $performer, $response );
117    }
118
119    /**
120     * Logs page impression events for specified pages
121     * like account creation or login page.
122     *
123     * @param PageReference $pageReference
124     * @param UserIdentity $performer The user viewing the page.
125     */
126    public function logPageImpression( PageReference $pageReference, UserIdentity $performer ): void {
127        $stream = $this->determineStreamForPage( $pageReference );
128
129        if ( !$stream ) {
130            return; // Not an instrumented page, do nothing.
131        }
132
133        $additionalData = [
134            'page_title' => $pageReference->getDBkey(),
135            'page_namespace' => $pageReference->getNamespace(),
136        ];
137        $this->doLogEvent( $stream, 'impression', $performer, $additionalData );
138    }
139
140    /**
141     * Determines the appropriate event stream based on the page title.
142     *
143     * @param PageReference $pageReference Reference to the special page.
144     * @return string|null The stream constant or null if the page is not instrumented.
145     */
146    private function determineStreamForPage( PageReference $pageReference ): ?string {
147        [ $canonicalName, ] = $this->specialPageFactory->resolveAlias( $pageReference->getDBkey() );
148        return $this->pageStreamMap[$canonicalName] ?? null;
149    }
150
151}