Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
19.10% covered (danger)
19.10%
17 / 89
0.00% covered (danger)
0.00%
0 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
HelpPanel
19.10% covered (danger)
19.10%
17 / 89
0.00% covered (danger)
0.00%
0 / 9
506.51
0.00% covered (danger)
0.00%
0 / 1
 getHelpPanelCtaButton
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
6
 getHelpPanelLinks
0.00% covered (danger)
0.00%
0 / 35
0.00% covered (danger)
0.00%
0 / 1
42
 shouldShowHelpPanelToUser
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 shouldShowHelpPanel
86.67% covered (warning)
86.67%
13 / 15
0.00% covered (danger)
0.00%
0 / 1
8.15
 shouldShowForReadingMode
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
56
 isHelpPanelEnabled
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getHelpDeskTitle
80.00% covered (warning)
80.00%
4 / 5
0.00% covered (danger)
0.00%
0 / 1
2.03
 getUserEmailConfigVars
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 isSuggestedEditRequest
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace GrowthExperiments;
4
5use GrowthExperiments\Config\GrowthConfigLoaderStaticTrait;
6use GrowthExperiments\HelpPanel\HelpPanelButton;
7use GrowthExperiments\HomepageModules\SuggestedEdits;
8use MediaWiki\Config\Config;
9use MediaWiki\Config\ConfigException;
10use MediaWiki\Html\Html;
11use MediaWiki\Language\RawMessage;
12use MediaWiki\MediaWikiServices;
13use MediaWiki\Output\OutputPage;
14use MediaWiki\Request\WebRequest;
15use MediaWiki\Title\Title;
16use MediaWiki\User\User;
17use MediaWiki\User\UserIdentity;
18use MessageLocalizer;
19use OOUI\Tag;
20
21class HelpPanel {
22    use GrowthConfigLoaderStaticTrait;
23
24    public const HELPDESK_QUESTION_TAG = 'help panel question';
25
26    /**
27     * @return Tag
28     * @throws ConfigException
29     */
30    public static function getHelpPanelCtaButton() {
31        $helpdeskTitle = self::getHelpDeskTitle(
32            GrowthExperimentsServices::wrap( MediaWikiServices::getInstance() )->getGrowthWikiConfig()
33        );
34        $btnWidgetArr = [
35            'label' => wfMessage( 'growthexperiments-help-panel-cta-button-text' )->text(),
36        ];
37        if ( $helpdeskTitle ) {
38            $btnWidgetArr['href'] = $helpdeskTitle->getLinkURL();
39        }
40        return ( new Tag( 'div' ) )
41            ->addClasses( [ 'mw-ge-help-panel-cta' ] )
42            ->appendContent( new HelpPanelButton( $btnWidgetArr ) );
43    }
44
45    /**
46     * @param MessageLocalizer $ml
47     * @param Config $wikiConfig
48     * @return array Links that should appear in the help panel. Exported to JS as wgGEHelpPanelLinks.
49     */
50    public static function getHelpPanelLinks(
51        MessageLocalizer $ml,
52        Config $wikiConfig
53    ) {
54        if ( !self::isHelpPanelEnabled() ) {
55            return [];
56        }
57
58        $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
59
60        $helpPanelLinks = Html::openElement( 'ul', [ 'class' => 'mw-ge-help-panel-links' ] );
61        foreach ( $wikiConfig->get( 'GEHelpPanelLinks' ) as $link ) {
62            $link = (array)$link;
63            $title = Title::newFromText( $link['title'] );
64            if ( $title ) {
65                $helpPanelLinks .= Html::rawElement(
66                    'li',
67                    [],
68                    $linkRenderer->makePreloadedLink( $title, $link['text'], '',
69                        [ 'target' => '_blank', 'data-link-id' => $link['id'] ?? '' ] )
70                );
71            }
72        }
73        $helpPanelLinks .= Html::closeElement( 'ul' );
74
75        $helpDeskTitle = self::getHelpDeskTitle( $wikiConfig );
76        $helpDeskLink = $helpDeskTitle ? $linkRenderer->makePreloadedLink(
77            $helpDeskTitle,
78            $ml->msg( 'growthexperiments-help-panel-community-help-desk-text' )->text(),
79            '',
80            [ 'target' => '_blank', 'data-link-id' => 'help-desk' ]
81        ) : null;
82
83        $viewMoreTitle = Title::newFromText( $wikiConfig->get( 'GEHelpPanelViewMoreTitle' ) );
84        $viewMoreLink = $viewMoreTitle ? $linkRenderer->makePreloadedLink(
85            $viewMoreTitle,
86            $ml->msg( 'growthexperiments-help-panel-editing-help-links-widget-view-more-link' )
87                ->text(),
88            '',
89            [ 'target' => '_blank', 'data-link-id' => 'view-more' ]
90        ) : null;
91
92        return [
93            'helpPanelLinks' => $helpPanelLinks,
94            'helpDeskLink' => $helpDeskLink,
95            'viewMoreLink' => $viewMoreLink
96        ];
97    }
98
99    /**
100     * Whether to show the help panel to a particular user.
101     *
102     * @param UserIdentity $user
103     * @return bool
104     */
105    public static function shouldShowHelpPanelToUser( UserIdentity $user ) {
106        if ( !self::isHelpPanelEnabled() ) {
107            return false;
108        }
109
110        $userOptionsLookup = MediaWikiServices::getInstance()->getUserOptionsLookup();
111        return (bool)$userOptionsLookup->getOption( $user, HelpPanelHooks::HELP_PANEL_PREFERENCES_TOGGLE );
112    }
113
114    /**
115     * Check if we should show help panel to user.
116     *
117     * @param OutputPage $out
118     * @param bool $checkAction
119     * @return bool
120     * @throws ConfigException
121     */
122    public static function shouldShowHelpPanel( OutputPage $out, $checkAction = true ): bool {
123        if ( !self::isHelpPanelEnabled() ) {
124            return false;
125        }
126
127        if ( !$out->getUser()->isNamed() ) {
128            return false;
129        }
130
131        if ( in_array( $out->getTitle()->getNamespace(),
132            self::getGrowthWikiConfig()->get( 'GEHelpPanelExcludedNamespaces' ) ) ) {
133            return false;
134        }
135        if ( $checkAction ) {
136            $action = $out->getRequest()->getVal( 'action', 'view' );
137            if ( !in_array( $action, [ 'edit', 'submit' ] ) &&
138                 !self::shouldShowForReadingMode( $out, $action ) ) {
139                return false;
140            }
141        }
142        if ( self::isSuggestedEditRequest( $out->getRequest() ) ) {
143            return true;
144        }
145        return self::shouldShowHelpPanelToUser( $out->getUser() );
146    }
147
148    /**
149     * If action=view, check if we are in allowed namespace.
150     *
151     * Note that views to talk titles will perform a look up for the subject title namespace,
152     * so specifying 4 (NS_PROJECT) as a namespace for which to enable help panel reading mode
153     * will also result in enabling 5 (NS_PROJECT_TALK) as an additional namespace.
154     *
155     * @param OutputPage $out
156     * @param string $action
157     * @return bool
158     * @throws ConfigException
159     */
160    public static function shouldShowForReadingMode( OutputPage $out, $action ) {
161        if ( $action !== 'view' ) {
162            return false;
163        }
164        $title = $out->getTitle();
165        if ( !$title ) {
166            return false;
167        }
168        if ( $title->isMainPage() ) {
169            // kowiki uses a Wikipedia namespace page as its Main_Page.
170            return false;
171        }
172        if ( $title->inNamespaces( NS_MAIN, NS_TALK ) &&
173            SuggestedEdits::isGuidanceEnabled( $out->getContext() ) &&
174            HomepageHooks::getClickId( $out->getContext() ) ) {
175            return true;
176        }
177        return in_array( $title->getSubjectPage()->getNamespace(),
178                   self::getGrowthWikiConfig()->get( 'GEHelpPanelReadingModeNamespaces' ) );
179    }
180
181    /**
182     * @return bool
183     */
184    public static function isHelpPanelEnabled() {
185        return MediaWikiServices::getInstance()->getMainConfig()->get( 'GEHelpPanelEnabled' );
186    }
187
188    /**
189     * Get the help desk title and expand the templates and magic words it may contain
190     *
191     * @param Config $wikiConfig
192     * @return null|Title
193     * @throws ConfigException
194     */
195    public static function getHelpDeskTitle( Config $wikiConfig ) {
196        $helpdeskTitle = $wikiConfig->get( 'GEHelpPanelHelpDeskTitle' );
197        if ( $helpdeskTitle === null ) {
198            return null;
199        }
200
201        // RawMessage is used here to expand magic words like {{#time:o}} - see T213186, T224224
202        $msg = new RawMessage( $helpdeskTitle );
203        return Title::newFromText( $msg->inContentLanguage()->text() );
204    }
205
206    /**
207     * Get the config vars needed to properly display the user email status
208     * in the question poster dialog used in the Help Panel as well as the
209     * Help and Mentorship modules.
210     *
211     * @param User $user
212     * @return array
213     */
214    public static function getUserEmailConfigVars( User $user ) {
215        return [
216            'wgGEHelpPanelUserEmail' => $user->getEmail(),
217            'wgGEHelpPanelUserEmailConfirmed' => $user->isEmailConfirmed(),
218        ];
219    }
220
221    /** Check if the request is from Special:Homepage to a Suggested Edit article.
222     *
223     * @param WebRequest $request
224     * @return bool
225     */
226    private static function isSuggestedEditRequest( WebRequest $request ): bool {
227        return $request->getBool( 'gesuggestededit' );
228    }
229}