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