Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 67 |
|
0.00% |
0 / 11 |
CRAP | |
0.00% |
0 / 1 |
Hooks | |
0.00% |
0 / 67 |
|
0.00% |
0 / 11 |
812 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
onResourceLoaderRegisterModules | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
6 | |||
onGetPreferences | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
onPreferencesGetLayout | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
6 | |||
onFetchChangesList | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
onSpecialPageBeforeExecute | |
0.00% |
0 / 19 |
|
0.00% |
0 / 1 |
72 | |||
onUserLogoutComplete | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
6 | |||
onResourceLoaderGetConfigVars | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
6 | |||
onOutputPageBodyAttributes | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
20 | |||
onSkinPageReadyConfig | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
onDifferenceEngineViewHeader | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
6 |
1 | <?php |
2 | /** |
3 | * This program is free software; you can redistribute it and/or modify |
4 | * it under the terms of the GNU General Public License as published by |
5 | * the Free Software Foundation; either version 2 of the License, or |
6 | * (at your option) any later version. |
7 | * |
8 | * This program is distributed in the hope that it will be useful, |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 | * GNU General Public License for more details. |
12 | * |
13 | * You should have received a copy of the GNU General Public License along |
14 | * with this program; if not, write to the Free Software Foundation, Inc., |
15 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
16 | * http://www.gnu.org/copyleft/gpl.html |
17 | * |
18 | * @file |
19 | */ |
20 | |
21 | namespace MediaWiki\Minerva; |
22 | |
23 | use ChangesList; |
24 | use ChangesListFilterGroup; |
25 | use DifferenceEngine; |
26 | use ExtensionRegistry; |
27 | use MediaWiki\Config\Config; |
28 | use MediaWiki\Diff\Hook\DifferenceEngineViewHeaderHook; |
29 | use MediaWiki\Hook\FetchChangesListHook; |
30 | use MediaWiki\Hook\OutputPageBodyAttributesHook; |
31 | use MediaWiki\Hook\PreferencesGetLayoutHook; |
32 | use MediaWiki\Hook\UserLogoutCompleteHook; |
33 | use MediaWiki\Html\Html; |
34 | use MediaWiki\Minerva\Skins\SkinMinerva; |
35 | use MediaWiki\Output\OutputPage; |
36 | use MediaWiki\Preferences\Hook\GetPreferencesHook; |
37 | use MediaWiki\ResourceLoader\Context; |
38 | use MediaWiki\ResourceLoader\Hook\ResourceLoaderGetConfigVarsHook; |
39 | use MediaWiki\ResourceLoader\Hook\ResourceLoaderRegisterModulesHook; |
40 | use MediaWiki\ResourceLoader\ResourceLoader; |
41 | use MediaWiki\Skins\Hook\SkinPageReadyConfigHook; |
42 | use MediaWiki\SpecialPage\Hook\SpecialPageBeforeExecuteHook; |
43 | use MediaWiki\SpecialPage\SpecialPage; |
44 | use MediaWiki\User\Options\UserOptionsLookup; |
45 | use MediaWiki\User\User; |
46 | use MobileContext; |
47 | use OldChangesList; |
48 | use Skin; |
49 | use Wikimedia\Rdbms\ConfiguredReadOnlyMode; |
50 | |
51 | /** |
52 | * Hook handlers for Minerva skin. |
53 | * |
54 | * Hook handler method names should be in the form of: |
55 | * on<HookName>() |
56 | */ |
57 | class Hooks implements |
58 | DifferenceEngineViewHeaderHook, |
59 | FetchChangesListHook, |
60 | GetPreferencesHook, |
61 | OutputPageBodyAttributesHook, |
62 | PreferencesGetLayoutHook, |
63 | ResourceLoaderGetConfigVarsHook, |
64 | ResourceLoaderRegisterModulesHook, |
65 | SkinPageReadyConfigHook, |
66 | SpecialPageBeforeExecuteHook, |
67 | UserLogoutCompleteHook |
68 | { |
69 | public const FEATURE_OVERFLOW_PAGE_ACTIONS = 'MinervaOverflowInPageActions'; |
70 | |
71 | private ConfiguredReadOnlyMode $configuredReadOnlyMode; |
72 | private SkinOptions $skinOptions; |
73 | private UserOptionsLookup $userOptionsLookup; |
74 | private ?MobileContext $mobileContext; |
75 | |
76 | public function __construct( |
77 | ConfiguredReadOnlyMode $configuredReadOnlyMode, |
78 | SkinOptions $skinOptions, |
79 | UserOptionsLookup $userOptionsLookup, |
80 | ?MobileContext $mobileContext |
81 | ) { |
82 | $this->configuredReadOnlyMode = $configuredReadOnlyMode; |
83 | $this->skinOptions = $skinOptions; |
84 | $this->userOptionsLookup = $userOptionsLookup; |
85 | $this->mobileContext = $mobileContext; |
86 | } |
87 | |
88 | /** |
89 | * ResourceLoaderRegisterModules hook handler. |
90 | * |
91 | * Registers: |
92 | * |
93 | * * EventLogging schema modules, if the EventLogging extension is loaded; |
94 | * * Modules for the Visual Editor overlay, if the VisualEditor extension is loaded; and |
95 | * * Modules for the notifications overlay, if the Echo extension is loaded. |
96 | * |
97 | * @see https://www.mediawiki.org/wiki/Manual:Hooks/ResourceLoaderRegisterModules |
98 | * |
99 | * @param ResourceLoader $resourceLoader |
100 | */ |
101 | public function onResourceLoaderRegisterModules( ResourceLoader $resourceLoader ): void { |
102 | if ( !ExtensionRegistry::getInstance()->isLoaded( 'MobileFrontend' ) ) { |
103 | $resourceLoader->register( [ |
104 | 'mobile.startup' => [ |
105 | 'dependencies' => [ 'mediawiki.searchSuggest' ], |
106 | 'localBasePath' => dirname( __DIR__ ), |
107 | 'remoteExtPath' => 'Minerva', |
108 | 'scripts' => 'resources/mobile.startup.stub.js', |
109 | ] |
110 | ] ); |
111 | } |
112 | } |
113 | |
114 | /** |
115 | * Adds Minerva-specific user preferences that can only be accessed via API |
116 | * |
117 | * @param User $user user whose preferences are being modified |
118 | * @param array[] &$prefs preferences description array, to be fed to a HTMLForm object |
119 | */ |
120 | public function onGetPreferences( $user, &$prefs ): void { |
121 | $minervaPrefs = [ |
122 | 'minerva-theme' => [ |
123 | 'type' => 'api' |
124 | ], |
125 | ]; |
126 | |
127 | $prefs += $minervaPrefs; |
128 | } |
129 | |
130 | /** |
131 | * PreferencesGetLayout hook handler. |
132 | * |
133 | * Use mobile layout in Special:Preferences |
134 | * @see https://www.mediawiki.org/wiki/Manual:Hooks/PreferencesGetLayout |
135 | * |
136 | * @param bool &$useMobileLayout |
137 | * @param string $skinName |
138 | * @param array $skinProperties |
139 | */ |
140 | public function onPreferencesGetLayout( &$useMobileLayout, $skinName, $skinProperties = [] ) { |
141 | if ( $skinName === 'minerva' ) { |
142 | $useMobileLayout = true; |
143 | } |
144 | } |
145 | |
146 | /** |
147 | * Disable recent changes enhanced mode (table mode) |
148 | * @see https://www.mediawiki.org/wiki/Manual:Hooks/FetchChangesList |
149 | * |
150 | * @param User $user |
151 | * @param Skin $skin |
152 | * @param ChangesList|null &$list |
153 | * @param ChangesListFilterGroup[] $groups |
154 | * @return bool|null |
155 | */ |
156 | public function onFetchChangesList( $user, $skin, &$list, $groups ) { |
157 | if ( $skin->getSkinName() === 'minerva' ) { |
158 | // The new changes list (table-based) does not work with Minerva |
159 | $list = new OldChangesList( $skin->getContext(), $groups ); |
160 | // returning false makes sure $list is used instead. |
161 | return false; |
162 | } |
163 | } |
164 | |
165 | /** |
166 | * Invocation of hook SpecialPageBeforeExecute |
167 | * |
168 | * We use this hook to ensure that login/account creation pages |
169 | * are redirected to HTTPS if they are not accessed via HTTPS and |
170 | * $wgSecureLogin == true - but only when using the |
171 | * mobile site. |
172 | * |
173 | * @param SpecialPage $special |
174 | * @param string $subpage |
175 | */ |
176 | public function onSpecialPageBeforeExecute( $special, $subpage ) { |
177 | $name = $special->getName(); |
178 | if ( !in_array( $name, [ 'Recentchanges', 'Userlogin', 'CreateAccount' ] ) ) { |
179 | return; |
180 | } |
181 | $skin = $special->getSkin(); |
182 | if ( !$skin instanceof SkinMinerva ) { |
183 | return; |
184 | } |
185 | $request = $special->getRequest(); |
186 | if ( $name === 'Recentchanges' ) { |
187 | $isEnhancedDefaultForUser = $this->userOptionsLookup |
188 | ->getBoolOption( $special->getUser(), 'usenewrc' ); |
189 | $enhanced = $request->getBool( 'enhanced', $isEnhancedDefaultForUser ); |
190 | if ( $enhanced ) { |
191 | $special->getOutput()->addHTML( Html::warningBox( |
192 | $special->msg( 'skin-minerva-recentchanges-warning-enhanced-not-supported' )->parse() |
193 | ) ); |
194 | } |
195 | } else { |
196 | // Add default warning message to Special:UserLogin and Special:UserCreate |
197 | // if no warning message set. |
198 | if ( |
199 | !$request->getCheck( 'warning' ) && |
200 | !$special->getUser()->isRegistered() && |
201 | !$request->wasPosted() |
202 | ) { |
203 | $request->setVal( 'warning', 'mobile-frontend-generic-login-new' ); |
204 | } |
205 | } |
206 | } |
207 | |
208 | /** |
209 | * UserLogoutComplete hook handler. |
210 | * Resets skin options if a user logout occurs - this is necessary as the |
211 | * RequestContextCreateSkinMobile hook runs before the UserLogout hook. |
212 | * |
213 | * @param User $user |
214 | * @param string &$inject_html |
215 | * @param string $oldName |
216 | */ |
217 | public function onUserLogoutComplete( $user, &$inject_html, $oldName ) { |
218 | if ( $this->mobileContext ) { |
219 | $this->skinOptions->setMinervaSkinOptions( $this->mobileContext, $this->mobileContext->getSkin() ); |
220 | } |
221 | } |
222 | |
223 | /** |
224 | * ResourceLoaderGetConfigVars hook handler. |
225 | * Used for setting JS variables which are pulled in dynamically with RL |
226 | * instead of embedded directly on the page with a script tag. |
227 | * These vars have a shorter cache-life than those in `getJsConfigVars`. |
228 | * |
229 | * @param array &$vars Array of variables to be added into the output of the RL startup module. |
230 | * @param string $skin |
231 | * @param Config $config |
232 | */ |
233 | public function onResourceLoaderGetConfigVars( array &$vars, $skin, Config $config ): void { |
234 | if ( $skin === 'minerva' ) { |
235 | // This is to let the UI adjust itself to a wiki that is always read-only. |
236 | // Ignore temporary read-only on live wikis, requires heavy DB check (T233458). |
237 | $roConf = $this->configuredReadOnlyMode; |
238 | $vars += [ |
239 | 'wgMinervaABSamplingRate' => $config->get( 'MinervaABSamplingRate' ), |
240 | 'wgMinervaReadOnly' => $roConf->isReadOnly(), |
241 | ]; |
242 | } |
243 | } |
244 | |
245 | /** |
246 | * Modifies the `<body>` element's attributes. |
247 | * |
248 | * By default, the `class` attribute is set to the output's "bodyClassName" |
249 | * property. |
250 | * |
251 | * @param OutputPage $out |
252 | * @param Skin $skin |
253 | * @param string[] &$bodyAttrs |
254 | */ |
255 | public function onOutputPageBodyAttributes( $out, $skin, &$bodyAttrs ): void { |
256 | $classes = $out->getProperty( 'bodyClassName' ); |
257 | $isMinerva = $skin instanceof SkinMinerva; |
258 | |
259 | if ( $isMinerva && $this->skinOptions->get( SkinOptions::HISTORY_IN_PAGE_ACTIONS ) ) { |
260 | // Class is used when page actions is modified to contain more elements |
261 | $classes .= ' minerva--history-page-action-enabled'; |
262 | } |
263 | |
264 | if ( $isMinerva ) { |
265 | $bodyAttrs['class'] .= ' ' . $classes; |
266 | } |
267 | } |
268 | |
269 | /** |
270 | * SkinPageReadyConfig hook handler |
271 | * |
272 | * Disable collapsible on page load |
273 | * |
274 | * @param Context $context |
275 | * @param mixed[] &$config Associative array of configurable options |
276 | */ |
277 | public function onSkinPageReadyConfig( |
278 | Context $context, |
279 | array &$config |
280 | ): void { |
281 | if ( $context->getSkin() === 'minerva' ) { |
282 | $config['search'] = false; |
283 | $config['collapsible'] = false; |
284 | $config['selectorLogoutLink'] = 'a.menu__item--logout[data-mw="interface"]'; |
285 | } |
286 | } |
287 | |
288 | /** |
289 | * Force inline diffs on mobile site. |
290 | * |
291 | * @param DifferenceEngine $differenceEngine |
292 | */ |
293 | public function onDifferenceEngineViewHeader( $differenceEngine ) { |
294 | $skin = $differenceEngine->getSkin(); |
295 | if ( $skin->getSkinName() !== 'minerva' ) { |
296 | return; |
297 | } |
298 | $differenceEngine->setSlotDiffOptions( [ |
299 | 'diff-type' => 'inline', |
300 | ] ); |
301 | } |
302 | } |