Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
24 / 24 |
|
100.00% |
3 / 3 |
CRAP | |
100.00% |
1 / 1 |
WikimediaEventsRequestDetailsLookup | |
100.00% |
24 / 24 |
|
100.00% |
3 / 3 |
14 | |
100.00% |
1 / 1 |
getEntryPoint | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
4 | |||
getMWEntryPointConstant | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getPlatformDetails | |
100.00% |
17 / 17 |
|
100.00% |
1 / 1 |
9 |
1 | <?php |
2 | |
3 | namespace WikimediaEvents\Services; |
4 | |
5 | use MediaWiki\Context\RequestContext; |
6 | |
7 | /** |
8 | * Looks up information about the current request, such as the platform and entry point. Used to de-duplicate code. |
9 | */ |
10 | class WikimediaEventsRequestDetailsLookup { |
11 | |
12 | /** |
13 | * @return string A string which represents the entry point (MW_ENTRY_POINT) for use in Prometheus labels |
14 | */ |
15 | public function getEntryPoint(): string { |
16 | $mwEntryPoint = $this->getMWEntryPointConstant(); |
17 | if ( $mwEntryPoint === 'index' ) { |
18 | // non-AJAX submission from user interface |
19 | // (for non-WMF this could also mean jobrunner, since jobs run post-send |
20 | // from index.php by default) |
21 | return 'index'; |
22 | } elseif ( $mwEntryPoint === 'api' || $mwEntryPoint === 'rest' ) { |
23 | return 'api'; |
24 | } else { |
25 | // jobrunner, maint/cli |
26 | return 'other'; |
27 | } |
28 | } |
29 | |
30 | /** |
31 | * @return string Returns the value of the MW_ENTRY_POINT constant. Mocked in PHPUnit tests. |
32 | */ |
33 | protected function getMWEntryPointConstant(): string { |
34 | return MW_ENTRY_POINT; |
35 | } |
36 | |
37 | /** |
38 | * Gets the platform name and whether the device is mobile, for use in Prometheus labels. |
39 | * |
40 | * @return string[] |
41 | */ |
42 | public function getPlatformDetails(): array { |
43 | // Because ::getEntryPoint only can use details from the main request, we don't want to support a use-case |
44 | // which has a non-main request context. |
45 | $context = RequestContext::getMain(); |
46 | |
47 | // It's possible to use Minerva on a desktop device, or Vector on a mobile |
48 | // device, but defining Minerva usage as a proxy for "is mobile" is good enough |
49 | // for monitoring. |
50 | $isMobile = $context->getSkin()->getSkinName() === 'minerva' ? '1' : '0'; |
51 | |
52 | // Would make sense to gate the following lines behind $entry === 'api', but |
53 | // the entrypoint is hardcoded via MW_ENTRY_POINT, which can't be overridden in tests. |
54 | |
55 | // Check if the request was Android/iOS/Commons app. |
56 | $userAgent = $context->getRequest()->getHeader( "User-agent" ); |
57 | $isWikipediaApp = strpos( $userAgent, "WikipediaApp/" ) === 0; |
58 | $isCommonsApp = strpos( $userAgent, "Commons/" ) === 0; |
59 | if ( $isWikipediaApp || $isCommonsApp ) { |
60 | // Consider apps to be "mobile" for instrumentation purposes |
61 | $isMobile = '1'; |
62 | } |
63 | if ( $isCommonsApp ) { |
64 | $platform = 'commons'; |
65 | } elseif ( strpos( $userAgent, "Android" ) > 0 ) { |
66 | $platform = 'android'; |
67 | } elseif ( strpos( $userAgent, "iOS" ) > 0 || strpos( $userAgent, "iPadOS" ) > 0 ) { |
68 | $platform = 'ios'; |
69 | } elseif ( $this->getEntryPoint() === 'index' ) { |
70 | $platform = 'web'; |
71 | } else { |
72 | $platform = 'unknown'; |
73 | } |
74 | |
75 | return [ 'platform' => $platform, 'isMobile' => $isMobile ]; |
76 | } |
77 | } |