Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 42 |
|
0.00% |
0 / 2 |
CRAP | |
0.00% |
0 / 1 |
RecentEditEntrypointRegistrationHandler | |
0.00% |
0 / 42 |
|
0.00% |
0 / 2 |
156 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
onBeforePageDisplay | |
0.00% |
0 / 40 |
|
0.00% |
0 / 1 |
132 |
1 | <?php |
2 | |
3 | declare( strict_types=1 ); |
4 | |
5 | namespace ContentTranslation\HookHandler; |
6 | |
7 | use ContentTranslation\Service\WikidataIdFetcher; |
8 | use ContentTranslation\SiteMapper; |
9 | use ContentTranslation\Store\RecentSignificantEditStore; |
10 | use ExtensionRegistry; |
11 | use MediaWiki\Hook\BeforePageDisplayHook; |
12 | use MediaWiki\MediaWikiServices; |
13 | use OutputPage; |
14 | use Skin; |
15 | |
16 | class RecentEditEntrypointRegistrationHandler implements BeforePageDisplayHook { |
17 | /** @var RecentSignificantEditStore */ |
18 | private $significantEditStore; |
19 | |
20 | /** @var WikidataIdFetcher */ |
21 | private $wikidataIdFetcher; |
22 | |
23 | public function __construct( |
24 | RecentSignificantEditStore $significantEditStore, |
25 | WikidataIdFetcher $wikidataIdFetcher |
26 | ) { |
27 | $this->significantEditStore = $significantEditStore; |
28 | $this->wikidataIdFetcher = $wikidataIdFetcher; |
29 | } |
30 | |
31 | /** |
32 | * This hook adds "ext.cx.entrypoints.recentedit" module, to support |
33 | * entrypoint inside articles, that encourages users to translate |
34 | * a section, they recently edited for the same page in another language. |
35 | * |
36 | * To support this entrypoint, a table named "cx_significant_edits" |
37 | * has been created, that stores the 10 latest "significant" edits, |
38 | * that affect at least one non-lead section, for each user. |
39 | * |
40 | * If such edits exist for the current article, then the |
41 | * "ext.cx.entrypoints.recentedit" module is added and |
42 | * "wgSectionTranslationRecentlyEditedSections" JS variable |
43 | * is set, containing an array of objects containing the page title |
44 | * and the sections edited for each language: |
45 | * ([{ "language": "en", page: "Moon", "sections": ["Formation"] }]). |
46 | * |
47 | * @param OutputPage $out |
48 | * @param Skin $skin |
49 | */ |
50 | public function onBeforePageDisplay( $out, $skin ): void { |
51 | $isMobileView = false; |
52 | if ( ExtensionRegistry::getInstance()->isLoaded( 'MobileFrontend' ) ) { |
53 | $mobileContext = MediaWikiServices::getInstance()->getService( 'MobileFrontend.Context' ); |
54 | $isMobileView = $mobileContext->shouldDisplayMobileView(); |
55 | } |
56 | |
57 | // This entrypoint should only be enabled for mobile web version |
58 | if ( !$isMobileView ) { |
59 | return; |
60 | } |
61 | |
62 | // This entrypoint should only be enabled for logged-in users |
63 | $user = $out->getUser(); |
64 | if ( !$user->isNamed() ) { |
65 | return; |
66 | } |
67 | |
68 | // This entrypoint should only be enabled for article pages |
69 | $isContentPage = $out->getTitle()->isContentPage(); |
70 | if ( !$isContentPage ) { |
71 | return; |
72 | } |
73 | |
74 | $currentLanguageCode = SiteMapper::getCurrentLanguageCode(); |
75 | // This entrypoint should only be enabled for wikis that have SectionTranslation enabled |
76 | $enabledLanguages = $out->getConfig()->get( 'SectionTranslationTargetLanguages' ); |
77 | $isSXEnabled = is_array( $enabledLanguages ) && in_array( $currentLanguageCode, $enabledLanguages ); |
78 | if ( !$isSXEnabled ) { |
79 | return; |
80 | } |
81 | |
82 | $recentUserEdits = []; |
83 | |
84 | // If current wiki family is not supported for this entrypoint, return |
85 | if ( !$this->significantEditStore->isCurrentWikiFamilySupported() ) { |
86 | return; |
87 | } |
88 | |
89 | $title = $out->getTitle(); |
90 | $qid = $this->wikidataIdFetcher->getWikidataId( $title->getPrefixedDBkey(), $currentLanguageCode ); |
91 | |
92 | if ( !$qid ) { |
93 | wfDebugLog( 'cx-entrypoints-recent-edit', 'qid not found' ); |
94 | return; |
95 | } |
96 | // get integer from Q id ("Q123") |
97 | $wikidataId = (int)filter_var( $qid, FILTER_SANITIZE_NUMBER_INT ); |
98 | |
99 | /** |
100 | * Fetch at most 10 objects representing rows inside "cx_significant_edits" table, |
101 | * that satisfy the below conditions: |
102 | * 1. Were made by the current user |
103 | * 2. Were done to an article with the current wikidata page id |
104 | * 3. Were done in a language different from the current one |
105 | */ |
106 | $edits = $this->significantEditStore->findEditsForPotentialSuggestions( |
107 | $user->getId(), |
108 | $wikidataId, |
109 | SiteMapper::getCurrentLanguageCode() |
110 | ); |
111 | |
112 | // We want to group the edited sections by language. For that reason, group the above |
113 | // RecentSignificantEdit instances to an associative array, that follow the below form: |
114 | // [ |
115 | // "en" => [ "language" => "en", "page" => "Moon", "sections" => ["Formation"] ], |
116 | // "es" => [ "language" => "es", "page" => "Luna", "sections" => ["FormaciĆ³n"] ] |
117 | // ] |
118 | foreach ( $edits as $edit ) { |
119 | $editLanguage = $edit->getLanguage(); |
120 | $recentUserEdits[$editLanguage]['language'] = $editLanguage; |
121 | $recentUserEdits[$editLanguage]['page'] = $edit->getPageTitle(); |
122 | |
123 | foreach ( $edit->getSectionTitles() as $sectionTitle ) { |
124 | $recentUserEdits[$editLanguage]['sections'][] = $sectionTitle; |
125 | } |
126 | } |
127 | |
128 | // If all the above conditions are met, add 'ext.cx.entrypoints.recentedit' entrypoint |
129 | $out->addModules( 'ext.cx.entrypoints.recentedit' ); |
130 | |
131 | // Add Javascript variable that will contain an array of objects containing |
132 | // the edited sections, the respective page title and the respective language. |
133 | $out->addJsConfigVars( 'wgSectionTranslationRecentlyEditedSections', |
134 | array_values( $recentUserEdits ) ); |
135 | } |
136 | } |