Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 51 |
|
0.00% |
0 / 12 |
CRAP | |
0.00% |
0 / 1 |
MobileSpecialPage | |
0.00% |
0 / 51 |
|
0.00% |
0 / 12 |
272 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
2 | |||
executeWhenAvailable | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
execute | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
12 | |||
setHeaders | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
renderUnavailableBanner | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
addModules | |
0.00% |
0 / 15 |
|
0.00% |
0 / 1 |
12 | |||
isListed | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
showPageNotFound | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
2 | |||
getDesktopUrl | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getUserOptionsLookup | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getUserGroupManager | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getUserFactory | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | use MediaWiki\CommentFormatter\CommentFormatter; |
4 | use MediaWiki\Config\Config; |
5 | use MediaWiki\Html\Html; |
6 | use MediaWiki\MediaWikiServices; |
7 | use MediaWiki\SpecialPage\SpecialPage; |
8 | use MediaWiki\User\Options\UserOptionsLookup; |
9 | use MediaWiki\User\UserFactory; |
10 | use MediaWiki\User\UserGroupManager; |
11 | use MobileFrontend\Hooks\HookRunner; |
12 | |
13 | /** |
14 | * Basic mobile implementation of SpecialPage to use in specific mobile special pages |
15 | */ |
16 | class MobileSpecialPage extends SpecialPage { |
17 | /** @var bool If true, the page will also be available on desktop */ |
18 | protected $hasDesktopVersion = false; |
19 | /** @var bool Whether this special page should appear on Special:SpecialPages */ |
20 | protected $listed = false; |
21 | /** @var Config MobileFrontend's config object */ |
22 | protected $config = null; |
23 | /** @var string a message key for the error message heading that should be shown on a 404 */ |
24 | protected $errorNotFoundTitleMsg = 'mobile-frontend-generic-404-title'; |
25 | /** @var string a message key for the error message description that should be shown on a 404 */ |
26 | protected $errorNotFoundDescriptionMsg = 'mobile-frontend-generic-404-desc'; |
27 | /** @var MobileContext */ |
28 | protected $mobileContext; |
29 | /** @var UserOptionsLookup */ |
30 | protected $userOptionsLookup; |
31 | /** @var UserGroupManager */ |
32 | protected $userGroupManager; |
33 | /** @var UserFactory */ |
34 | protected $userFactory; |
35 | /** @var CommentFormatter */ |
36 | protected $commentFormatter; |
37 | |
38 | /** |
39 | * @param string $page |
40 | */ |
41 | public function __construct( $page ) { |
42 | parent::__construct( $page ); |
43 | |
44 | $services = MediaWikiServices::getInstance(); |
45 | $this->config = $services->getService( 'MobileFrontend.Config' ); |
46 | $this->mobileContext = $services->getService( 'MobileFrontend.Context' ); |
47 | $this->userOptionsLookup = $services->getUserOptionsLookup(); |
48 | $this->userGroupManager = $services->getUserGroupManager(); |
49 | $this->userFactory = $services->getUserFactory(); |
50 | $this->commentFormatter = $services->getCommentFormatter(); |
51 | } |
52 | |
53 | /** |
54 | * Executes the page when available in the current $mode |
55 | * @param string|null $subPage parameter as subpage of specialpage |
56 | */ |
57 | public function executeWhenAvailable( $subPage ) { |
58 | } |
59 | |
60 | /** |
61 | * Checks the availability of the special page in actual mode and display the page, if available |
62 | * @param string|null $subPage parameter submitted as "subpage" |
63 | */ |
64 | public function execute( $subPage ) { |
65 | $out = $this->getOutput(); |
66 | $out->addBodyClasses( 'mw-mf-special-page' ); |
67 | $out->setProperty( 'desktopUrl', $this->getDesktopUrl( $subPage ) ); |
68 | if ( !$this->mobileContext->shouldDisplayMobileView() && |
69 | !$this->hasDesktopVersion ) { |
70 | # We are not going to return any real content |
71 | $out->setStatusCode( 404 ); |
72 | $this->renderUnavailableBanner( $this->msg( 'mobile-frontend-requires-mobile' )->parse() ); |
73 | } else { |
74 | $this->executeWhenAvailable( $subPage ); |
75 | } |
76 | } |
77 | |
78 | /** |
79 | * Add modules to headers |
80 | */ |
81 | public function setHeaders() { |
82 | parent::setHeaders(); |
83 | $this->addModules(); |
84 | } |
85 | |
86 | /** |
87 | * Renders a banner telling the user the page is unavailable |
88 | * |
89 | * @param string $msg Message to display |
90 | */ |
91 | protected function renderUnavailableBanner( $msg ) { |
92 | $out = $this->getOutput(); |
93 | $out->setPageTitleMsg( $this->msg( 'mobile-frontend-requires-title' ) ); |
94 | $out->addHTML( Html::warningBox( $msg ) ); |
95 | } |
96 | |
97 | /** |
98 | * Add mobile special page specific modules (styles and scripts) |
99 | */ |
100 | protected function addModules() { |
101 | $out = $this->getOutput(); |
102 | $rl = $out->getResourceLoader(); |
103 | $name = $this->getName(); |
104 | $id = strtolower( $name ); |
105 | // FIXME: These modules should not exist in MobileFrontend, please see: |
106 | // * T109277: [EPIC]: Use core watchlist code for mobile experience |
107 | // * T91201 [EPIC] Accessibility settings/preferences |
108 | // Possible values: |
109 | // * mobile.special.watchlist.scripts |
110 | // * mobile.special.watchlist.styles |
111 | // * mobile.special.mobileoptions.styles |
112 | // * mobile.special.mobileoptions.scripts |
113 | $specialStyleModuleName = 'mobile.special.' . $id . '.styles'; |
114 | $specialScriptModuleName = 'mobile.special.' . $id . '.scripts'; |
115 | |
116 | if ( $rl->isModuleRegistered( $specialStyleModuleName ) ) { |
117 | $out->addModuleStyles( [ |
118 | // FIXME: mobile.special.styles should be replaced with mediawiki.special module |
119 | 'mobile.special.styles', |
120 | $specialStyleModuleName |
121 | ] ); |
122 | } |
123 | |
124 | if ( $rl->isModuleRegistered( $specialScriptModuleName ) ) { |
125 | $out->addModules( $specialScriptModuleName ); |
126 | } |
127 | $hookRunner = new HookRunner( MediaWikiServices::getInstance()->getHookContainer() ); |
128 | $hookRunner->onMobileSpecialPageStyles( $id, $out ); |
129 | } |
130 | |
131 | /** |
132 | * Returns if this page is listed on Special:SpecialPages |
133 | * @return bool |
134 | */ |
135 | public function isListed() { |
136 | return $this->listed; |
137 | } |
138 | |
139 | /** |
140 | * Render mobile specific error page, when special page can not be found |
141 | */ |
142 | protected function showPageNotFound() { |
143 | $this->getOutput()->setStatusCode( 404 ); |
144 | $this->getOutput()->addHTML( |
145 | MobileUI::contentElement( |
146 | Html::errorBox( |
147 | $this->msg( $this->errorNotFoundDescriptionMsg )->text(), |
148 | $this->msg( $this->errorNotFoundTitleMsg )->text() |
149 | ) |
150 | ) |
151 | ); |
152 | } |
153 | |
154 | /** |
155 | * When overridden in a descendant class, returns desktop URL for this special page |
156 | * @param string|null $subPage Subpage passed in URL |
157 | * @return string|null Desktop URL for this special page or null if a standard one should be used |
158 | */ |
159 | public function getDesktopUrl( $subPage ) { |
160 | return null; |
161 | } |
162 | |
163 | /** |
164 | * Get a user options lookup object. |
165 | * @return UserOptionsLookup |
166 | */ |
167 | protected function getUserOptionsLookup(): UserOptionsLookup { |
168 | return $this->userOptionsLookup; |
169 | } |
170 | |
171 | /** |
172 | * Get a user group manager object. |
173 | * @return UserGroupManager |
174 | */ |
175 | protected function getUserGroupManager(): UserGroupManager { |
176 | return $this->userGroupManager; |
177 | } |
178 | |
179 | /** |
180 | * Get a user factory object for creating UserIdentify object. |
181 | * @return UserFactory |
182 | */ |
183 | protected function getUserFactory(): UserFactory { |
184 | return $this->userFactory; |
185 | } |
186 | } |