Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 82 |
|
0.00% |
0 / 7 |
CRAP | |
0.00% |
0 / 1 |
FundraiserLandingPage | |
0.00% |
0 / 82 |
|
0.00% |
0 / 7 |
552 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
execute | |
0.00% |
0 / 52 |
|
0.00% |
0 / 1 |
110 | |||
fundraiserLandingPageMakeSafe | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
20 | |||
fundraiserLandingPageSwitchLanguage | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
12 | |||
fundraiserLandingPageSwitchCountry | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
12 | |||
isFundraiseUp | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getFundraiseUpJavascript | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace MediaWiki\Extension\FundraiserLandingPage\Specials; |
4 | |
5 | /* |
6 | * SpecialPage definition for FundraiserLandingPage. Extending UnlistedSpecialPage |
7 | * since this page does not need to listed in Special:SpecialPages. |
8 | * |
9 | * @author Peter Gehres <pgehres@wikimedia.org> |
10 | */ |
11 | |
12 | use Parser; |
13 | use Title; |
14 | use UnlistedSpecialPage; |
15 | |
16 | class FundraiserLandingPage extends UnlistedSpecialPage { |
17 | public function __construct() { |
18 | parent::__construct( 'FundraiserLandingPage' ); |
19 | } |
20 | |
21 | /** |
22 | * @param string $par |
23 | */ |
24 | public function execute( $par ) { |
25 | global $wgFundraiserLPDefaults, $wgFundraiserLandingPageMaxAge, |
26 | $wgContributionTrackingFundraiserMaintenance, |
27 | $wgContributionTrackingFundraiserMaintenanceUnsched; |
28 | |
29 | if ( $wgContributionTrackingFundraiserMaintenance |
30 | || $wgContributionTrackingFundraiserMaintenanceUnsched |
31 | ) { |
32 | $this->getOutput()->redirect( |
33 | Title::newFromText( 'Special:FundraiserMaintenance' )->getFullURL(), '302' |
34 | ); |
35 | } |
36 | |
37 | $out = $this->getOutput(); |
38 | $request = $this->getRequest(); |
39 | |
40 | // Set squid age |
41 | $out->setCdnMaxage( $wgFundraiserLandingPageMaxAge ); |
42 | |
43 | if ( $this->isFundraiseUp() ) { |
44 | $out->addScript( $this->getFundraiseUpJavascript() ); |
45 | } |
46 | $this->setHeaders(); |
47 | |
48 | // set the page title to something useful |
49 | $titleMsg = $this->msg( 'donate_interface-make-your-donation' ); |
50 | if ( !is_callable( [ $out, 'setPageTitleMsg' ] ) ) { |
51 | // Backward compatibility with MW < 1.41 |
52 | $out->setPageTitle( $titleMsg ); |
53 | } else { |
54 | // MW >= 1.41 |
55 | $out->setPageTitleMsg( $titleMsg ); |
56 | } |
57 | |
58 | // and add a <meta name="description"> tag to give search engines a useful blurb |
59 | $out->addMeta( 'description', $this->msg( 'fundraiserlandingpage-meta-description' ) ); |
60 | |
61 | // And mark the page as allowed for search engine indexing (default for SpecialPages is noindex) |
62 | $out->setIndexPolicy( 'index' ); |
63 | |
64 | // clear output variable to be safe |
65 | $output = ''; |
66 | |
67 | // begin generating the template call |
68 | $template = self::fundraiserLandingPageMakeSafe( |
69 | $request->getText( 'template', $wgFundraiserLPDefaults[ 'template' ] ) |
70 | ); |
71 | $output .= "{{ $template\n"; |
72 | |
73 | // get the required variables (except template and country) to use for the landing page |
74 | $requiredParams = [ |
75 | 'appeal', |
76 | 'appeal-template', |
77 | 'form-template', |
78 | 'form-countryspecific' |
79 | ]; |
80 | foreach ( $requiredParams as $requiredParam ) { |
81 | $param = self::fundraiserLandingPageMakeSafe( |
82 | $request->getText( $requiredParam, $wgFundraiserLPDefaults[$requiredParam] ) |
83 | ); |
84 | // Add them to the template call |
85 | $output .= "| $requiredParam = $param\n"; |
86 | } |
87 | |
88 | // get the country code |
89 | $country = $request->getVal( 'country' ); |
90 | // If country still isn't set, set it to the default |
91 | if ( !$country ) { |
92 | $country = $wgFundraiserLPDefaults[ 'country' ]; |
93 | } |
94 | $country = self::fundraiserLandingPageMakeSafe( $country ); |
95 | $output .= "| country = $country\n"; |
96 | |
97 | // @phan-suppress-next-line PhanUselessBinaryAddRight |
98 | $excludeKeys = $requiredParams + [ 'template', 'country', 'title' ]; |
99 | |
100 | // if there are any other parameters passed in the querystring, add them |
101 | if ( $request->getQueryValuesOnly() ) { |
102 | foreach ( $request->getQueryValuesOnly() as $k_unsafe => $v_unsafe ) { |
103 | // skip the required variables |
104 | if ( in_array( $k_unsafe, $excludeKeys ) ) { |
105 | continue; |
106 | } |
107 | // get the variable's name and value |
108 | $key = self::fundraiserLandingPageMakeSafe( $k_unsafe ); |
109 | $val = self::fundraiserLandingPageMakeSafe( $v_unsafe ); |
110 | // print to the template in wiki-syntax |
111 | $output .= "| $key = $val\n"; |
112 | } |
113 | } |
114 | |
115 | // close the template call |
116 | $output .= "}}"; |
117 | |
118 | // Hijack parser internals to workaround T156184. This should be safe |
119 | // since we've sanitized all params. |
120 | $parserOptions = $out->parserOptions(); |
121 | $parserOptions->setAllowUnsafeRawHtml( true ); |
122 | |
123 | // print the output to the page |
124 | $out->addWikiTextAsInterface( $output ); |
125 | } |
126 | |
127 | /** |
128 | * This function limits the possible characters passed as template keys and |
129 | * values to letters, numbers, hyphens, underscores, and the forward slash. |
130 | * The function also performs standard escaping of the passed values. |
131 | * |
132 | * @param mixed $value The unsafe value to escape and check for invalid characters |
133 | * @param string $default A default value to return if when making the $string safe no |
134 | * results are returned. |
135 | * |
136 | * @return string A string matching the regex or an empty string |
137 | * @suppress SecurityCheck-DoubleEscaped double escaping is on purpose per the inline |
138 | * comment |
139 | */ |
140 | private static function fundraiserLandingPageMakeSafe( $value, $default = '' ) { |
141 | if ( $default != '' ) { |
142 | $default = self::fundraiserLandingPageMakeSafe( $default ); |
143 | } |
144 | |
145 | if ( !is_string( $value ) ) { |
146 | // In case someone has passed in an array as a request parameter |
147 | return $default; |
148 | } |
149 | |
150 | $num = preg_match( '/^([-a-zA-Z0-9_\/]+)$/', $value, $matches ); |
151 | |
152 | if ( $num == 1 ) { |
153 | # theoretically this is overkill, but better safe than sorry |
154 | return wfEscapeWikiText( htmlspecialchars( $matches[1] ) ); |
155 | } |
156 | return $default; |
157 | } |
158 | |
159 | /** |
160 | * Attempts to load a language localized template. Precedence is Language, |
161 | * Country, Root. It is assumed that all parts of the title are separated |
162 | * with '/'. |
163 | * |
164 | * @param Parser $parser Reference to the WM parser object |
165 | * @param string $page The template page root to load |
166 | * @param string $language The language to attempt to localize onto |
167 | * @param string $country The country to attempt to localize onto |
168 | * |
169 | * @return array The wikitext template |
170 | */ |
171 | public static function fundraiserLandingPageSwitchLanguage( $parser, $page = '', |
172 | $language = 'en', $country = 'XX' |
173 | ) { |
174 | $page = self::fundraiserLandingPageMakeSafe( $page ); |
175 | $country = self::fundraiserLandingPageMakeSafe( $country, 'XX' ); |
176 | $language = self::fundraiserLandingPageMakeSafe( $language, 'en' ); |
177 | |
178 | if ( Title::newFromText( "Template:$page/$language/$country" )->exists() ) { |
179 | $tpltext = "$page/$language/$country"; |
180 | } elseif ( Title::newFromText( "Template:$page/$language" )->exists() ) { |
181 | $tpltext = "$page/$language"; |
182 | } else { |
183 | // If all the variants don't exist, then merely return the base. If |
184 | // something really screwy happened and the base doesn't exist either |
185 | // we will let the WM error handler sort it out. |
186 | |
187 | $tpltext = $page; |
188 | } |
189 | |
190 | return [ "{{Template:$tpltext}}", 'noparse' => false ]; |
191 | } |
192 | |
193 | /** |
194 | * Attempts to load a language localized template. Precedence is Country, |
195 | * Language, Root. It is assumed that all parts of the title are separated |
196 | * with '/'. |
197 | * |
198 | * @param Parser $parser Reference to the WM parser object |
199 | * @param string $page The template page root to load |
200 | * @param string $country The country to attempt to localize onto |
201 | * @param string $language The language to attempt to localize onto |
202 | * |
203 | * @return array The wikitext template |
204 | */ |
205 | public static function fundraiserLandingPageSwitchCountry( $parser, $page = '', $country = 'XX', |
206 | $language = 'en' |
207 | ) { |
208 | $page = self::fundraiserLandingPageMakeSafe( $page ); |
209 | $country = self::fundraiserLandingPageMakeSafe( $country, 'XX' ); |
210 | $language = self::fundraiserLandingPageMakeSafe( $language, 'en' ); |
211 | |
212 | if ( Title::newFromText( "Template:$page/$country/$language" )->exists() ) { |
213 | $tpltext = "$page/$country/$language"; |
214 | |
215 | } elseif ( Title::newFromText( "Template:$page/$country" )->exists() ) { |
216 | $tpltext = "$page/$country"; |
217 | |
218 | } else { |
219 | // If all the variants don't exist, then merely return the base. If |
220 | // something really screwy happened and the base doesn't exist either |
221 | // we will let the WM error handler sort it out. |
222 | |
223 | $tpltext = $page; |
224 | } |
225 | |
226 | return [ "{{Template:$tpltext}}", 'noparse' => false ]; |
227 | } |
228 | |
229 | /** |
230 | * Check if template is fundraiseup |
231 | * @return bool |
232 | */ |
233 | private function isFundraiseUp() { |
234 | return $this->getRequest()->getVal( 'fundraiseupScript' ) === "1"; |
235 | } |
236 | |
237 | /** |
238 | * Javascript to add fundraiseup to DonateWiki page |
239 | * |
240 | * @return string |
241 | */ |
242 | private function getFundraiseUpJavascript() { |
243 | return <<<EOF |
244 | <script>(function(w,d,s,n,a){if(!w[n]){var l='call,catch,on,once,set,then,track' |
245 | .split(','),i,o=function(n){return'function'==typeof n?o.l.push([arguments])&&o |
246 | :function(){return o.l.push([n,arguments])&&o}},t=d.getElementsByTagName(s)[0], |
247 | j=d.createElement(s);j.async=!0;j.src='https://cdn.fundraiseup.com/widget/'+a; |
248 | t.parentNode.insertBefore(j,t);o.s=Date.now();o.v=4;o.h=w.location.href;o.l=[]; |
249 | for(i=0;i<7;i++)o[l[i]]=o(l[i]);w[n]=o} |
250 | })(window,document,'script','FundraiseUp','AVLMPSRU'); |
251 | </script> |
252 | EOF; |
253 | } |
254 | } |