Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 42
0.00% covered (danger)
0.00%
0 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
RecentEditEntrypointRegistrationHandler
0.00% covered (danger)
0.00%
0 / 42
0.00% covered (danger)
0.00%
0 / 2
156
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
 onBeforePageDisplay
0.00% covered (danger)
0.00%
0 / 40
0.00% covered (danger)
0.00%
0 / 1
132
1<?php
2
3declare( strict_types=1 );
4
5namespace ContentTranslation\HookHandler;
6
7use ContentTranslation\Service\WikidataIdFetcher;
8use ContentTranslation\SiteMapper;
9use ContentTranslation\Store\RecentSignificantEditStore;
10use MediaWiki\MediaWikiServices;
11use MediaWiki\Output\Hook\BeforePageDisplayHook;
12use MediaWiki\Output\OutputPage;
13use MediaWiki\Registration\ExtensionRegistry;
14use MobileContext;
15use Skin;
16
17class 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}