Index: branches/Gadgets3.0/Gadgets.php |
— | — | @@ -17,8 +17,8 @@ |
18 | 18 | die( 1 ); |
19 | 19 | } |
20 | 20 | |
21 | | -if ( version_compare( $wgVersion, '1.17alpha', '<' ) ) { |
22 | | - die( "This version of Extension:Gadgets requires MediaWiki 1.17+\n" ); |
| 21 | +if ( version_compare( $wgVersion, '1.18alpha', '<' ) ) { |
| 22 | + die( "This version of Extension:Gadgets requires MediaWiki 1.18+\n" ); |
23 | 23 | } |
24 | 24 | |
25 | 25 | $wgExtensionCredits['other'][] = array( |
— | — | @@ -39,12 +39,17 @@ |
40 | 40 | $wgExtensionMessagesFiles['Gadgets'] = $dir . 'Gadgets.i18n.php'; |
41 | 41 | $wgExtensionAliasesFiles['Gadgets'] = $dir . 'Gadgets.alias.php'; |
42 | 42 | |
| 43 | +$wgAutoloadClasses['Gadget'] = $dir . 'backend/Gadget.php'; |
| 44 | +$wgAutoloadClasses['GadgetHooks'] = $dir . 'backend/GadgetHooks.php'; |
| 45 | +$wgAutoloadClasses['GadgetResourceLoaderModule'] = $dir . 'backend/GadgetResourceLoaderModule.php'; |
| 46 | + |
43 | 47 | $wgAutoloadClasses['ApiQueryGadgetCategories'] = $dir . 'api/ApiQueryGadgetCategories.php'; |
44 | 48 | $wgAutoloadClasses['ApiQueryGadgets'] = $dir . 'api/ApiQueryGadgets.php'; |
45 | | -$wgAutoloadClasses['Gadget'] = $dir . 'backend/Gadgets_body.php'; |
46 | | -$wgAutoloadClasses['GadgetHooks'] = $dir . 'backend/Gadgets_body.php'; |
47 | | -$wgAutoloadClasses['GadgetResourceLoaderModule'] = $dir . 'backend/Gadgets_body.php'; |
| 49 | + |
| 50 | + |
48 | 51 | $wgAutoloadClasses['SpecialGadgets'] = $dir . 'ui/SpecialGadgets.php'; |
| 52 | +$wgAutoloadClasses['GadgetsView'] = $dir . 'ui/GadgetsView.php'; |
| 53 | +$wgAutoloadClasses['MainGadgetsView'] = $dir . 'ui/MainGadgetsView.php'; |
49 | 54 | |
50 | 55 | $wgSpecialPages['Gadgets'] = 'SpecialGadgets'; |
51 | 56 | $wgSpecialPageGroups['Gadgets'] = 'wiki'; |
Index: branches/Gadgets3.0/backend/Gadgets_body.php |
— | — | @@ -1,567 +0,0 @@ |
2 | | -<?php |
3 | | -/** |
4 | | - * Gadgets extension - lets users select custom javascript gadgets |
5 | | - * |
6 | | - * |
7 | | - * For more info see http://mediawiki.org/wiki/Extension:Gadgets |
8 | | - * |
9 | | - * @file |
10 | | - * @ingroup Extensions |
11 | | - * @author Daniel Kinzler, brightbyte.de |
12 | | - * @copyright © 2007 Daniel Kinzler |
13 | | - * @license GNU General Public Licence 2.0 or later |
14 | | - */ |
15 | | - |
16 | | -class GadgetHooks { |
17 | | - |
18 | | - /** |
19 | | - * ArticleSaveComplete hook handler. |
20 | | - * |
21 | | - * @param $article Article |
22 | | - * @param $user User |
23 | | - * @param $text String: New page text |
24 | | - */ |
25 | | - public static function articleSaveComplete( $article, $user, $text ) { |
26 | | - //update cache if MediaWiki:Gadgets-definition was edited |
27 | | - $title = $article->mTitle; |
28 | | - if( $title->getNamespace() == NS_MEDIAWIKI && $title->getText() == 'Gadgets-definition' ) { |
29 | | - Gadget::loadStructuredList( $text ); |
30 | | - } |
31 | | - return true; |
32 | | - } |
33 | | - |
34 | | - /** |
35 | | - * GetPreferences hook handler. |
36 | | - * @param $user User |
37 | | - * @param $preferences Array: Preference descriptions |
38 | | - */ |
39 | | - public static function getPreferences( $user, &$preferences ) { |
40 | | - $gadgets = Gadget::loadStructuredList(); |
41 | | - if (!$gadgets) return true; |
42 | | - |
43 | | - $options = array(); |
44 | | - $default = array(); |
45 | | - foreach( $gadgets as $section => $thisSection ) { |
46 | | - $available = array(); |
47 | | - foreach( $thisSection as $gadget ) { |
48 | | - if ( $gadget->isAllowed( $user ) ) { |
49 | | - $gname = $gadget->getName(); |
50 | | - $available[$gadget->getDescription()] = $gname; |
51 | | - if ( $gadget->isEnabled( $user ) ) { |
52 | | - $default[] = $gname; |
53 | | - } |
54 | | - } |
55 | | - } |
56 | | - if ( $section !== '' ) { |
57 | | - $section = wfMsgExt( "gadget-section-$section", 'parseinline' ); |
58 | | - if ( count ( $available ) ) { |
59 | | - $options[$section] = $available; |
60 | | - } |
61 | | - } else { |
62 | | - $options = array_merge( $options, $available ); |
63 | | - } |
64 | | - } |
65 | | - |
66 | | - $preferences['gadgets-intro'] = |
67 | | - array( |
68 | | - 'type' => 'info', |
69 | | - 'label' => ' ', |
70 | | - 'default' => Xml::tags( 'tr', array(), |
71 | | - Xml::tags( 'td', array( 'colspan' => 2 ), |
72 | | - wfMsgExt( 'gadgets-prefstext', 'parse' ) ) ), |
73 | | - 'section' => 'gadgets', |
74 | | - 'raw' => 1, |
75 | | - 'rawrow' => 1, |
76 | | - ); |
77 | | - |
78 | | - $preferences['gadgets'] = |
79 | | - array( |
80 | | - 'type' => 'multiselect', |
81 | | - 'options' => $options, |
82 | | - 'section' => 'gadgets', |
83 | | - 'label' => ' ', |
84 | | - 'prefix' => 'gadget-', |
85 | | - 'default' => $default, |
86 | | - ); |
87 | | - |
88 | | - return true; |
89 | | - } |
90 | | - |
91 | | - /** |
92 | | - * ResourceLoaderRegisterModules hook handler. |
93 | | - * @param $resourceLoader ResourceLoader |
94 | | - */ |
95 | | - public static function registerModules( &$resourceLoader ) { |
96 | | - $gadgets = Gadget::loadList(); |
97 | | - if ( !$gadgets ) { |
98 | | - return true; |
99 | | - } |
100 | | - foreach ( $gadgets as $g ) { |
101 | | - $module = $g->getModule(); |
102 | | - if ( $module ) { |
103 | | - $resourceLoader->register( $g->getModuleName(), $module ); |
104 | | - } |
105 | | - } |
106 | | - return true; |
107 | | - } |
108 | | - |
109 | | - /** |
110 | | - * BeforePageDisplay hook handler. |
111 | | - * @param $out OutputPage |
112 | | - */ |
113 | | - public static function beforePageDisplay( $out ) { |
114 | | - global $wgUser; |
115 | | - |
116 | | - wfProfileIn( __METHOD__ ); |
117 | | - |
118 | | - $gadgets = Gadget::loadList(); |
119 | | - if ( !$gadgets ) { |
120 | | - wfProfileOut( __METHOD__ ); |
121 | | - return true; |
122 | | - } |
123 | | - |
124 | | - $lb = new LinkBatch(); |
125 | | - $lb->setCaller( __METHOD__ ); |
126 | | - $pages = array(); |
127 | | - |
128 | | - foreach ( $gadgets as $gadget ) { |
129 | | - if ( $gadget->isEnabled( $wgUser ) && $gadget->isAllowed( $wgUser ) ) { |
130 | | - if ( $gadget->hasModule() ) { |
131 | | - $out->addModules( $gadget->getModuleName() ); |
132 | | - } |
133 | | - foreach ( $gadget->getLegacyScripts() as $page ) { |
134 | | - $lb->add( NS_MEDIAWIKI, $page ); |
135 | | - $pages[] = $page; |
136 | | - } |
137 | | - } |
138 | | - } |
139 | | - |
140 | | - $lb->execute( __METHOD__ ); |
141 | | - |
142 | | - $done = array(); |
143 | | - foreach ( $pages as $page ) { |
144 | | - if ( isset( $done[$page] ) ) continue; |
145 | | - $done[$page] = true; |
146 | | - self::applyScript( $page, $out ); |
147 | | - } |
148 | | - wfProfileOut( __METHOD__ ); |
149 | | - |
150 | | - return true; |
151 | | - } |
152 | | - |
153 | | - /** |
154 | | - * Adds one legacy script to output. |
155 | | - * |
156 | | - * @param $page String: Unprefixed page title |
157 | | - * @param $out OutputPage |
158 | | - */ |
159 | | - private static function applyScript( $page, $out ) { |
160 | | - global $wgJsMimeType; |
161 | | - |
162 | | - # bug 22929: disable gadgets on sensitive pages. Scripts loaded through the |
163 | | - # ResourceLoader handle this in OutputPage::getModules() |
164 | | - # TODO: make this extension load everything via RL, then we don't need to worry |
165 | | - # about any of this. |
166 | | - if( $out->getAllowedModules( ResourceLoaderModule::TYPE_SCRIPTS ) < ResourceLoaderModule::ORIGIN_USER_SITEWIDE ){ |
167 | | - return; |
168 | | - } |
169 | | - |
170 | | - $t = Title::makeTitleSafe( NS_MEDIAWIKI, $page ); |
171 | | - if ( !$t ) return; |
172 | | - |
173 | | - $u = $t->getLocalURL( 'action=raw&ctype=' . $wgJsMimeType ); |
174 | | - $out->addScriptFile( $u, $t->getLatestRevID() ); |
175 | | - } |
176 | | - |
177 | | - /** |
178 | | - * UnitTestsList hook handler |
179 | | - * @param $files Array: List of extension test files |
180 | | - */ |
181 | | - public static function unitTestsList( $files ) { |
182 | | - $files[] = dirname( __FILE__ ) . '/Gadgets_tests.php'; |
183 | | - return true; |
184 | | - } |
185 | | -} |
186 | | - |
187 | | -/** |
188 | | - * Wrapper for one gadget. |
189 | | - */ |
190 | | -class Gadget { |
191 | | - /** |
192 | | - * Increment this when changing class structure |
193 | | - */ |
194 | | - const GADGET_CLASS_VERSION = 5; |
195 | | - |
196 | | - private $version = self::GADGET_CLASS_VERSION, |
197 | | - $scripts = array(), |
198 | | - $styles = array(), |
199 | | - $dependencies = array(), |
200 | | - $name, |
201 | | - $definition, |
202 | | - $resourceLoaded = false, |
203 | | - $requiredRights = array(), |
204 | | - $onByDefault = false, |
205 | | - $category; |
206 | | - |
207 | | - /** |
208 | | - * Creates an instance of this class from definition in MediaWiki:Gadgets-definition |
209 | | - * @param $definition String: Gadget definition |
210 | | - * @return Mixed: Instance of Gadget class or false if $definition is invalid |
211 | | - */ |
212 | | - public static function newFromDefinition( $definition ) { |
213 | | - $m = array(); |
214 | | - if ( !preg_match( '/^\*+ *([a-zA-Z](?:[-_:.\w\d ]*[a-zA-Z0-9])?)(\s*\[.*?\])?\s*((\|[^|]*)+)\s*$/', $definition, $m ) ) { |
215 | | - return false; |
216 | | - } |
217 | | - //NOTE: the gadget name is used as part of the name of a form field, |
218 | | - // and must follow the rules defined in http://www.w3.org/TR/html4/types.html#type-cdata |
219 | | - // Also, title-normalization applies. |
220 | | - $gadget = new Gadget(); |
221 | | - $gadget->name = trim( str_replace(' ', '_', $m[1] ) ); |
222 | | - $gadget->definition = $definition; |
223 | | - $options = trim( $m[2], ' []' ); |
224 | | - foreach ( preg_split( '/\s*\|\s*/', $options, -1, PREG_SPLIT_NO_EMPTY ) as $option ) { |
225 | | - $arr = preg_split( '/\s*=\s*/', $option, 2 ); |
226 | | - $option = $arr[0]; |
227 | | - if ( isset( $arr[1] ) ) { |
228 | | - $params = explode( ',', $arr[1] ); |
229 | | - $params = array_map( 'trim', $params ); |
230 | | - } else { |
231 | | - $params = array(); |
232 | | - } |
233 | | - switch ( $option ) { |
234 | | - case 'ResourceLoader': |
235 | | - $gadget->resourceLoaded = true; |
236 | | - break; |
237 | | - case 'dependencies': |
238 | | - $gadget->dependencies = $params; |
239 | | - break; |
240 | | - case 'rights': |
241 | | - $gadget->requiredRights = $params; |
242 | | - break; |
243 | | - case 'default': |
244 | | - $gadget->onByDefault = true; |
245 | | - break; |
246 | | - } |
247 | | - } |
248 | | - foreach ( preg_split( '/\s*\|\s*/', $m[3], -1, PREG_SPLIT_NO_EMPTY ) as $page ) { |
249 | | - $page = "Gadget-$page"; |
250 | | - if ( preg_match( '/\.js/', $page ) ) { |
251 | | - $gadget->scripts[] = $page; |
252 | | - } elseif ( preg_match( '/\.css/', $page ) ) { |
253 | | - $gadget->styles[] = $page; |
254 | | - } |
255 | | - } |
256 | | - return $gadget; |
257 | | - } |
258 | | - |
259 | | - /** |
260 | | - * @return String: Gadget name |
261 | | - */ |
262 | | - public function getName() { |
263 | | - return $this->name; |
264 | | - } |
265 | | - |
266 | | - /** |
267 | | - * @return String: Gadget description parsed into HTML |
268 | | - */ |
269 | | - public function getDescription() { |
270 | | - return wfMessage( "gadget-{$this->getName()}" )->parse(); |
271 | | - } |
272 | | - |
273 | | - /** |
274 | | - * @return String: Wikitext of gadget description |
275 | | - */ |
276 | | - public function getRawDescription() { |
277 | | - return wfMessage( "gadget-{$this->getName()}" )->plain(); |
278 | | - } |
279 | | - |
280 | | - /** |
281 | | - * @return String: Name of category (aka section) our gadget belongs to. Empty string if none. |
282 | | - */ |
283 | | - public function getCategory() { |
284 | | - return $this->category; |
285 | | - } |
286 | | - |
287 | | - /** |
288 | | - * @return String: Name of ResourceLoader module for this gadget |
289 | | - */ |
290 | | - public function getModuleName() { |
291 | | - return "ext.gadget.{$this->name}"; |
292 | | - } |
293 | | - |
294 | | - /** |
295 | | - * Checks whether this is an instance of an older version of this class deserialized from cache |
296 | | - * @return Boolean |
297 | | - */ |
298 | | - public function isOutdated() { |
299 | | - return $this->version != self::GADGET_CLASS_VERSION; |
300 | | - } |
301 | | - |
302 | | - /** |
303 | | - * Checks whether this gadget is enabled for given user |
304 | | - * |
305 | | - * @param $user User: user to check against |
306 | | - * @return Boolean |
307 | | - */ |
308 | | - public function isEnabled( $user ) { |
309 | | - return (bool)$user->getOption( "gadget-{$this->name}", $this->onByDefault ); |
310 | | - } |
311 | | - |
312 | | - /** |
313 | | - * Checks whether given user has permissions to use this gadget |
314 | | - * |
315 | | - * @param $user User: user to check against |
316 | | - * @return Boolean |
317 | | - */ |
318 | | - public function isAllowed( $user ) { |
319 | | - return count( array_intersect( $this->requiredRights, $user->getRights() ) ) == count( $this->requiredRights ); |
320 | | - } |
321 | | - |
322 | | - /** |
323 | | - * @return Boolean: Whether this gadget is on by default for everyone (but can be disabled in preferences) |
324 | | - */ |
325 | | - public function isOnByDefault() { |
326 | | - return $this->onByDefault; |
327 | | - } |
328 | | - |
329 | | - /** |
330 | | - * @return Boolean: Whether all of this gadget's JS components support ResourceLoader |
331 | | - */ |
332 | | - public function supportsResourceLoader() { |
333 | | - return $this->resourceLoaded; |
334 | | - } |
335 | | - |
336 | | - /** |
337 | | - * @return Boolean: Whether this gadget has resources that can be loaded via ResourceLoader |
338 | | - */ |
339 | | - public function hasModule() { |
340 | | - return count( $this->styles ) |
341 | | - + ( $this->supportsResourceLoader() ? count( $this->scripts ) : 0 ) |
342 | | - > 0; |
343 | | - } |
344 | | - |
345 | | - /** |
346 | | - * @return String: Definition for this gadget from MediaWiki:gadgets-definition |
347 | | - */ |
348 | | - public function getDefinition() { |
349 | | - return $this->definition; |
350 | | - } |
351 | | - |
352 | | - /** |
353 | | - * @return Array: Array of pages with JS not prefixed with namespace |
354 | | - */ |
355 | | - public function getScripts() { |
356 | | - return $this->scripts; |
357 | | - } |
358 | | - |
359 | | - /** |
360 | | - * @return Array: Array of pages with CSS not prefixed with namespace |
361 | | - */ |
362 | | - public function getStyles() { |
363 | | - return $this->styles; |
364 | | - } |
365 | | - |
366 | | - /** |
367 | | - * @return Array: Array of all of this gadget's resources |
368 | | - */ |
369 | | - public function getScriptsAndStyles() { |
370 | | - return array_merge( $this->scripts, $this->styles ); |
371 | | - } |
372 | | - |
373 | | - /** |
374 | | - * Returns module for ResourceLoader, see getModuleName() for its name. |
375 | | - * If our gadget has no scripts or styles suitable for RL, false will be returned. |
376 | | - * @return Mixed: GadgetResourceLoaderModule or false |
377 | | - */ |
378 | | - public function getModule() { |
379 | | - $pages = array(); |
380 | | - foreach( $this->styles as $style ) { |
381 | | - $pages['MediaWiki:' . $style] = array( 'type' => 'style' ); |
382 | | - } |
383 | | - if ( $this->supportsResourceLoader() ) { |
384 | | - foreach ( $this->scripts as $script ) { |
385 | | - $pages['MediaWiki:' . $script] = array( 'type' => 'script' ); |
386 | | - } |
387 | | - } |
388 | | - if ( !count( $pages ) ) { |
389 | | - return null; |
390 | | - } |
391 | | - return new GadgetResourceLoaderModule( $pages, $this->dependencies ); |
392 | | - } |
393 | | - |
394 | | - /** |
395 | | - * Returns list of scripts that don't support ResourceLoader |
396 | | - * @return Array |
397 | | - */ |
398 | | - public function getLegacyScripts() { |
399 | | - if ( $this->supportsResourceLoader() ) { |
400 | | - return array(); |
401 | | - } |
402 | | - return $this->scripts; |
403 | | - } |
404 | | - |
405 | | - /** |
406 | | - * Returns names of resources this gadget depends on |
407 | | - * @return Array |
408 | | - */ |
409 | | - public function getDependencies() { |
410 | | - return $this->dependencies; |
411 | | - } |
412 | | - |
413 | | - /** |
414 | | - * Returns array of permissions required by this gadget |
415 | | - * @return Array |
416 | | - */ |
417 | | - public function getRequiredRights() { |
418 | | - return $this->requiredRights; |
419 | | - } |
420 | | - |
421 | | - /** |
422 | | - * Loads and returns a list of all gadgets |
423 | | - * @return Mixed: Array of gadgets or false |
424 | | - */ |
425 | | - public static function loadList() { |
426 | | - static $gadgets = null; |
427 | | - |
428 | | - if ( $gadgets !== null ) return $gadgets; |
429 | | - |
430 | | - wfProfileIn( __METHOD__ ); |
431 | | - $struct = self::loadStructuredList(); |
432 | | - if ( !$struct ) { |
433 | | - $gadgets = $struct; |
434 | | - wfProfileOut( __METHOD__ ); |
435 | | - return $gadgets; |
436 | | - } |
437 | | - |
438 | | - $gadgets = array(); |
439 | | - foreach ( $struct as $section => $entries ) { |
440 | | - $gadgets = array_merge( $gadgets, $entries ); |
441 | | - } |
442 | | - wfProfileOut( __METHOD__ ); |
443 | | - |
444 | | - return $gadgets; |
445 | | - } |
446 | | - |
447 | | - /** |
448 | | - * Checks whether gadget list from cache can be used. |
449 | | - * @return Boolean |
450 | | - */ |
451 | | - private static function isValidList( $gadgets ) { |
452 | | - if ( !is_array( $gadgets ) ) return false; |
453 | | - // Check if we have 1) array of gadgets 2) the gadgets are up to date |
454 | | - // One check is enough |
455 | | - foreach ( $gadgets as $section => $list ) { |
456 | | - foreach ( $list as $g ) { |
457 | | - if ( !( $g instanceof Gadget ) || $g->isOutdated() ) { |
458 | | - return false; |
459 | | - } else { |
460 | | - return true; |
461 | | - } |
462 | | - } |
463 | | - } |
464 | | - return true; // empty array |
465 | | - } |
466 | | - |
467 | | - /** |
468 | | - * Loads list of gadgets and returns it as associative array of sections with gadgets |
469 | | - * e.g. array( 'sectionnname1' => array( $gadget1, $gadget2), |
470 | | - * 'sectionnname2' => array( $gadget3 ) ); |
471 | | - * @param $forceNewText String: New text of MediaWiki:gadgets-sdefinition. If specified, will |
472 | | - * force a purge of cache and recreation of the gadget list. |
473 | | - * @return Mixed: Array or false |
474 | | - */ |
475 | | - public static function loadStructuredList( $forceNewText = null ) { |
476 | | - global $wgMemc; |
477 | | - |
478 | | - static $gadgets = null; |
479 | | - if ( $gadgets !== null && $forceNewText === null ) return $gadgets; |
480 | | - |
481 | | - wfProfileIn( __METHOD__ ); |
482 | | - $key = wfMemcKey( 'gadgets-definition', self::GADGET_CLASS_VERSION ); |
483 | | - |
484 | | - if ( $forceNewText === null ) { |
485 | | - //cached? |
486 | | - $gadgets = $wgMemc->get( $key ); |
487 | | - if ( self::isValidList( $gadgets ) ) { |
488 | | - wfProfileOut( __METHOD__ ); |
489 | | - return $gadgets; |
490 | | - } |
491 | | - |
492 | | - $g = wfMsgForContentNoTrans( "gadgets-definition" ); |
493 | | - if ( wfEmptyMsg( "gadgets-definition", $g ) ) { |
494 | | - $gadgets = false; |
495 | | - wfProfileOut( __METHOD__ ); |
496 | | - return $gadgets; |
497 | | - } |
498 | | - } else { |
499 | | - $g = $forceNewText; |
500 | | - } |
501 | | - |
502 | | - $g = preg_replace( '/<!--.*-->/s', '', $g ); |
503 | | - $g = preg_split( '/(\r\n|\r|\n)+/', $g ); |
504 | | - |
505 | | - $gadgets = array(); |
506 | | - $section = ''; |
507 | | - |
508 | | - foreach ( $g as $line ) { |
509 | | - $m = array(); |
510 | | - if ( preg_match( '/^==+ *([^*:\s|]+?)\s*==+\s*$/', $line, $m ) ) { |
511 | | - $section = $m[1]; |
512 | | - } |
513 | | - else { |
514 | | - $gadget = self::newFromDefinition( $line ); |
515 | | - if ( $gadget ) { |
516 | | - $gadgets[$section][$gadget->getName()] = $gadget; |
517 | | - $gadget->category = $section; |
518 | | - } |
519 | | - } |
520 | | - } |
521 | | - |
522 | | - //cache for a while. gets purged automatically when MediaWiki:Gadgets-definition is edited |
523 | | - $wgMemc->set( $key, $gadgets, 60*60*24 ); |
524 | | - $source = $forceNewText !== null ? 'input text' : 'MediaWiki:Gadgets-definition'; |
525 | | - wfDebug( __METHOD__ . ": $source parsed, cache entry $key updated\n"); |
526 | | - wfProfileOut( __METHOD__ ); |
527 | | - |
528 | | - return $gadgets; |
529 | | - } |
530 | | -} |
531 | | - |
532 | | -/** |
533 | | - * Class representing a list of resources for one gadget |
534 | | - */ |
535 | | -class GadgetResourceLoaderModule extends ResourceLoaderWikiModule { |
536 | | - private $pages, $dependencies; |
537 | | - |
538 | | - /** |
539 | | - * Creates an instance of this class |
540 | | - * @param $pages Array: Associative array of pages in ResourceLoaderWikiModule-compatible |
541 | | - * format, for example: |
542 | | - * array( |
543 | | - * 'MediaWiki:Gadget-foo.js' => array( 'type' => 'script' ), |
544 | | - * 'MediaWiki:Gadget-foo.css' => array( 'type' => 'style' ), |
545 | | - * ) |
546 | | - * @param $dependencies Array: Names of resources this module depends on |
547 | | - */ |
548 | | - public function __construct( $pages, $dependencies ) { |
549 | | - $this->pages = $pages; |
550 | | - $this->dependencies = $dependencies; |
551 | | - } |
552 | | - |
553 | | - /** |
554 | | - * Overrides the abstract function from ResourceLoaderWikiModule class |
555 | | - * @return Array: $pages passed to __construct() |
556 | | - */ |
557 | | - protected function getPages( ResourceLoaderContext $context ) { |
558 | | - return $this->pages; |
559 | | - } |
560 | | - |
561 | | - /** |
562 | | - * Overrides ResourceLoaderModule::getDependencies() |
563 | | - * @return Array: Names of resources this module depends on |
564 | | - */ |
565 | | - public function getDependencies() { |
566 | | - return $this->dependencies; |
567 | | - } |
568 | | -} |
Index: branches/Gadgets3.0/backend/Gadget.php |
— | — | @@ -0,0 +1,347 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | + |
| 5 | +/** |
| 6 | + * Wrapper for one gadget. |
| 7 | + */ |
| 8 | +class Gadget { |
| 9 | + /** |
| 10 | + * Increment this when changing class structure |
| 11 | + */ |
| 12 | + const GADGET_CLASS_VERSION = 5; |
| 13 | + |
| 14 | + private $version = self::GADGET_CLASS_VERSION, |
| 15 | + $scripts = array(), |
| 16 | + $styles = array(), |
| 17 | + $dependencies = array(), |
| 18 | + $name, |
| 19 | + $definition, |
| 20 | + $resourceLoaded = false, |
| 21 | + $requiredRights = array(), |
| 22 | + $onByDefault = false, |
| 23 | + $category; |
| 24 | + |
| 25 | + /** |
| 26 | + * Creates an instance of this class from definition in MediaWiki:Gadgets-definition |
| 27 | + * @param $definition String: Gadget definition |
| 28 | + * @return Mixed: Instance of Gadget class or false if $definition is invalid |
| 29 | + */ |
| 30 | + public static function newFromDefinition( $definition ) { |
| 31 | + $m = array(); |
| 32 | + if ( !preg_match( '/^\*+ *([a-zA-Z](?:[-_:.\w\d ]*[a-zA-Z0-9])?)(\s*\[.*?\])?\s*((\|[^|]*)+)\s*$/', $definition, $m ) ) { |
| 33 | + return false; |
| 34 | + } |
| 35 | + //NOTE: the gadget name is used as part of the name of a form field, |
| 36 | + // and must follow the rules defined in http://www.w3.org/TR/html4/types.html#type-cdata |
| 37 | + // Also, title-normalization applies. |
| 38 | + $gadget = new Gadget(); |
| 39 | + $gadget->name = trim( str_replace(' ', '_', $m[1] ) ); |
| 40 | + $gadget->definition = $definition; |
| 41 | + $options = trim( $m[2], ' []' ); |
| 42 | + foreach ( preg_split( '/\s*\|\s*/', $options, -1, PREG_SPLIT_NO_EMPTY ) as $option ) { |
| 43 | + $arr = preg_split( '/\s*=\s*/', $option, 2 ); |
| 44 | + $option = $arr[0]; |
| 45 | + if ( isset( $arr[1] ) ) { |
| 46 | + $params = explode( ',', $arr[1] ); |
| 47 | + $params = array_map( 'trim', $params ); |
| 48 | + } else { |
| 49 | + $params = array(); |
| 50 | + } |
| 51 | + switch ( $option ) { |
| 52 | + case 'ResourceLoader': |
| 53 | + $gadget->resourceLoaded = true; |
| 54 | + break; |
| 55 | + case 'dependencies': |
| 56 | + $gadget->dependencies = $params; |
| 57 | + break; |
| 58 | + case 'rights': |
| 59 | + $gadget->requiredRights = $params; |
| 60 | + break; |
| 61 | + case 'default': |
| 62 | + $gadget->onByDefault = true; |
| 63 | + break; |
| 64 | + } |
| 65 | + } |
| 66 | + foreach ( preg_split( '/\s*\|\s*/', $m[3], -1, PREG_SPLIT_NO_EMPTY ) as $page ) { |
| 67 | + $page = "Gadget-$page"; |
| 68 | + if ( preg_match( '/\.js/', $page ) ) { |
| 69 | + $gadget->scripts[] = $page; |
| 70 | + } elseif ( preg_match( '/\.css/', $page ) ) { |
| 71 | + $gadget->styles[] = $page; |
| 72 | + } |
| 73 | + } |
| 74 | + return $gadget; |
| 75 | + } |
| 76 | + |
| 77 | + /** |
| 78 | + * @return String: Gadget name |
| 79 | + */ |
| 80 | + public function getName() { |
| 81 | + return $this->name; |
| 82 | + } |
| 83 | + |
| 84 | + /** |
| 85 | + * @return String: Gadget description parsed into HTML |
| 86 | + */ |
| 87 | + public function getDescription() { |
| 88 | + return wfMessage( "gadget-{$this->getName()}" )->parse(); |
| 89 | + } |
| 90 | + |
| 91 | + /** |
| 92 | + * @return String: Wikitext of gadget description |
| 93 | + */ |
| 94 | + public function getRawDescription() { |
| 95 | + return wfMessage( "gadget-{$this->getName()}" )->plain(); |
| 96 | + } |
| 97 | + |
| 98 | + /** |
| 99 | + * @return String: Name of category (aka section) our gadget belongs to. Empty string if none. |
| 100 | + */ |
| 101 | + public function getCategory() { |
| 102 | + return $this->category; |
| 103 | + } |
| 104 | + |
| 105 | + /** |
| 106 | + * @return String: Name of ResourceLoader module for this gadget |
| 107 | + */ |
| 108 | + public function getModuleName() { |
| 109 | + return "ext.gadget.{$this->name}"; |
| 110 | + } |
| 111 | + |
| 112 | + /** |
| 113 | + * Checks whether this is an instance of an older version of this class deserialized from cache |
| 114 | + * @return Boolean |
| 115 | + */ |
| 116 | + public function isOutdated() { |
| 117 | + return $this->version != self::GADGET_CLASS_VERSION; |
| 118 | + } |
| 119 | + |
| 120 | + /** |
| 121 | + * Checks whether this gadget is enabled for given user |
| 122 | + * |
| 123 | + * @param $user User: user to check against |
| 124 | + * @return Boolean |
| 125 | + */ |
| 126 | + public function isEnabled( $user ) { |
| 127 | + return (bool)$user->getOption( "gadget-{$this->name}", $this->onByDefault ); |
| 128 | + } |
| 129 | + |
| 130 | + /** |
| 131 | + * Checks whether given user has permissions to use this gadget |
| 132 | + * |
| 133 | + * @param $user User: user to check against |
| 134 | + * @return Boolean |
| 135 | + */ |
| 136 | + public function isAllowed( $user ) { |
| 137 | + return count( array_intersect( $this->requiredRights, $user->getRights() ) ) == count( $this->requiredRights ); |
| 138 | + } |
| 139 | + |
| 140 | + /** |
| 141 | + * @return Boolean: Whether this gadget is on by default for everyone (but can be disabled in preferences) |
| 142 | + */ |
| 143 | + public function isOnByDefault() { |
| 144 | + return $this->onByDefault; |
| 145 | + } |
| 146 | + |
| 147 | + /** |
| 148 | + * @return Boolean: Whether all of this gadget's JS components support ResourceLoader |
| 149 | + */ |
| 150 | + public function supportsResourceLoader() { |
| 151 | + return $this->resourceLoaded; |
| 152 | + } |
| 153 | + |
| 154 | + /** |
| 155 | + * @return Boolean: Whether this gadget has resources that can be loaded via ResourceLoader |
| 156 | + */ |
| 157 | + public function hasModule() { |
| 158 | + return count( $this->styles ) |
| 159 | + + ( $this->supportsResourceLoader() ? count( $this->scripts ) : 0 ) |
| 160 | + > 0; |
| 161 | + } |
| 162 | + |
| 163 | + /** |
| 164 | + * @return String: Definition for this gadget from MediaWiki:gadgets-definition |
| 165 | + */ |
| 166 | + public function getDefinition() { |
| 167 | + return $this->definition; |
| 168 | + } |
| 169 | + |
| 170 | + /** |
| 171 | + * @return Array: Array of pages with JS not prefixed with namespace |
| 172 | + */ |
| 173 | + public function getScripts() { |
| 174 | + return $this->scripts; |
| 175 | + } |
| 176 | + |
| 177 | + /** |
| 178 | + * @return Array: Array of pages with CSS not prefixed with namespace |
| 179 | + */ |
| 180 | + public function getStyles() { |
| 181 | + return $this->styles; |
| 182 | + } |
| 183 | + |
| 184 | + /** |
| 185 | + * @return Array: Array of all of this gadget's resources |
| 186 | + */ |
| 187 | + public function getScriptsAndStyles() { |
| 188 | + return array_merge( $this->scripts, $this->styles ); |
| 189 | + } |
| 190 | + |
| 191 | + /** |
| 192 | + * Returns module for ResourceLoader, see getModuleName() for its name. |
| 193 | + * If our gadget has no scripts or styles suitable for RL, false will be returned. |
| 194 | + * @return Mixed: GadgetResourceLoaderModule or false |
| 195 | + */ |
| 196 | + public function getModule() { |
| 197 | + $pages = array(); |
| 198 | + foreach( $this->styles as $style ) { |
| 199 | + $pages['MediaWiki:' . $style] = array( 'type' => 'style' ); |
| 200 | + } |
| 201 | + if ( $this->supportsResourceLoader() ) { |
| 202 | + foreach ( $this->scripts as $script ) { |
| 203 | + $pages['MediaWiki:' . $script] = array( 'type' => 'script' ); |
| 204 | + } |
| 205 | + } |
| 206 | + if ( !count( $pages ) ) { |
| 207 | + return null; |
| 208 | + } |
| 209 | + return new GadgetResourceLoaderModule( $pages, $this->dependencies ); |
| 210 | + } |
| 211 | + |
| 212 | + /** |
| 213 | + * Returns list of scripts that don't support ResourceLoader |
| 214 | + * @return Array |
| 215 | + */ |
| 216 | + public function getLegacyScripts() { |
| 217 | + if ( $this->supportsResourceLoader() ) { |
| 218 | + return array(); |
| 219 | + } |
| 220 | + return $this->scripts; |
| 221 | + } |
| 222 | + |
| 223 | + /** |
| 224 | + * Returns names of resources this gadget depends on |
| 225 | + * @return Array |
| 226 | + */ |
| 227 | + public function getDependencies() { |
| 228 | + return $this->dependencies; |
| 229 | + } |
| 230 | + |
| 231 | + /** |
| 232 | + * Returns array of permissions required by this gadget |
| 233 | + * @return Array |
| 234 | + */ |
| 235 | + public function getRequiredRights() { |
| 236 | + return $this->requiredRights; |
| 237 | + } |
| 238 | + |
| 239 | + /** |
| 240 | + * Loads and returns a list of all gadgets |
| 241 | + * @return Mixed: Array of gadgets or false |
| 242 | + */ |
| 243 | + public static function loadList() { |
| 244 | + static $gadgets = null; |
| 245 | + |
| 246 | + if ( $gadgets !== null ) return $gadgets; |
| 247 | + |
| 248 | + wfProfileIn( __METHOD__ ); |
| 249 | + $struct = self::loadStructuredList(); |
| 250 | + if ( !$struct ) { |
| 251 | + $gadgets = $struct; |
| 252 | + wfProfileOut( __METHOD__ ); |
| 253 | + return $gadgets; |
| 254 | + } |
| 255 | + |
| 256 | + $gadgets = array(); |
| 257 | + foreach ( $struct as $section => $entries ) { |
| 258 | + $gadgets = array_merge( $gadgets, $entries ); |
| 259 | + } |
| 260 | + wfProfileOut( __METHOD__ ); |
| 261 | + |
| 262 | + return $gadgets; |
| 263 | + } |
| 264 | + |
| 265 | + /** |
| 266 | + * Checks whether gadget list from cache can be used. |
| 267 | + * @return Boolean |
| 268 | + */ |
| 269 | + private static function isValidList( $gadgets ) { |
| 270 | + if ( !is_array( $gadgets ) ) return false; |
| 271 | + // Check if we have 1) array of gadgets 2) the gadgets are up to date |
| 272 | + // One check is enough |
| 273 | + foreach ( $gadgets as $section => $list ) { |
| 274 | + foreach ( $list as $g ) { |
| 275 | + if ( !( $g instanceof Gadget ) || $g->isOutdated() ) { |
| 276 | + return false; |
| 277 | + } else { |
| 278 | + return true; |
| 279 | + } |
| 280 | + } |
| 281 | + } |
| 282 | + return true; // empty array |
| 283 | + } |
| 284 | + |
| 285 | + /** |
| 286 | + * Loads list of gadgets and returns it as associative array of sections with gadgets |
| 287 | + * e.g. array( 'sectionnname1' => array( $gadget1, $gadget2), |
| 288 | + * 'sectionnname2' => array( $gadget3 ) ); |
| 289 | + * @param $forceNewText String: New text of MediaWiki:gadgets-sdefinition. If specified, will |
| 290 | + * force a purge of cache and recreation of the gadget list. |
| 291 | + * @return Mixed: Array or false |
| 292 | + */ |
| 293 | + public static function loadStructuredList( $forceNewText = null ) { |
| 294 | + global $wgMemc; |
| 295 | + |
| 296 | + static $gadgets = null; |
| 297 | + if ( $gadgets !== null && $forceNewText === null ) return $gadgets; |
| 298 | + |
| 299 | + wfProfileIn( __METHOD__ ); |
| 300 | + $key = wfMemcKey( 'gadgets-definition', self::GADGET_CLASS_VERSION ); |
| 301 | + |
| 302 | + if ( $forceNewText === null ) { |
| 303 | + //cached? |
| 304 | + $gadgets = $wgMemc->get( $key ); |
| 305 | + if ( self::isValidList( $gadgets ) ) { |
| 306 | + wfProfileOut( __METHOD__ ); |
| 307 | + return $gadgets; |
| 308 | + } |
| 309 | + |
| 310 | + $g = wfMsgForContentNoTrans( "gadgets-definition" ); |
| 311 | + if ( wfEmptyMsg( "gadgets-definition", $g ) ) { |
| 312 | + $gadgets = false; |
| 313 | + wfProfileOut( __METHOD__ ); |
| 314 | + return $gadgets; |
| 315 | + } |
| 316 | + } else { |
| 317 | + $g = $forceNewText; |
| 318 | + } |
| 319 | + |
| 320 | + $g = preg_replace( '/<!--.*-->/s', '', $g ); |
| 321 | + $g = preg_split( '/(\r\n|\r|\n)+/', $g ); |
| 322 | + |
| 323 | + $gadgets = array(); |
| 324 | + $section = ''; |
| 325 | + |
| 326 | + foreach ( $g as $line ) { |
| 327 | + $m = array(); |
| 328 | + if ( preg_match( '/^==+ *([^*:\s|]+?)\s*==+\s*$/', $line, $m ) ) { |
| 329 | + $section = $m[1]; |
| 330 | + } |
| 331 | + else { |
| 332 | + $gadget = self::newFromDefinition( $line ); |
| 333 | + if ( $gadget ) { |
| 334 | + $gadgets[$section][$gadget->getName()] = $gadget; |
| 335 | + $gadget->category = $section; |
| 336 | + } |
| 337 | + } |
| 338 | + } |
| 339 | + |
| 340 | + //cache for a while. gets purged automatically when MediaWiki:Gadgets-definition is edited |
| 341 | + $wgMemc->set( $key, $gadgets, 60*60*24 ); |
| 342 | + $source = $forceNewText !== null ? 'input text' : 'MediaWiki:Gadgets-definition'; |
| 343 | + wfDebug( __METHOD__ . ": $source parsed, cache entry $key updated\n"); |
| 344 | + wfProfileOut( __METHOD__ ); |
| 345 | + |
| 346 | + return $gadgets; |
| 347 | + } |
| 348 | +} |
\ No newline at end of file |
Property changes on: branches/Gadgets3.0/backend/Gadget.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 349 | + native |
Index: branches/Gadgets3.0/backend/GadgetHooks.php |
— | — | @@ -0,0 +1,184 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Gadgets extension - lets users select custom javascript gadgets |
| 5 | + * |
| 6 | + * |
| 7 | + * For more info see http://mediawiki.org/wiki/Extension:Gadgets |
| 8 | + * |
| 9 | + * @file |
| 10 | + * @ingroup Extensions |
| 11 | + * @author Daniel Kinzler, brightbyte.de |
| 12 | + * @copyright © 2007 Daniel Kinzler |
| 13 | + * @license GNU General Public Licence 2.0 or later |
| 14 | + */ |
| 15 | + |
| 16 | +class GadgetHooks { |
| 17 | + |
| 18 | + /** |
| 19 | + * ArticleSaveComplete hook handler. |
| 20 | + * |
| 21 | + * @param $article Article |
| 22 | + * @param $user User |
| 23 | + * @param $text String: New page text |
| 24 | + */ |
| 25 | + public static function articleSaveComplete( $article, $user, $text ) { |
| 26 | + //update cache if MediaWiki:Gadgets-definition was edited |
| 27 | + $title = $article->mTitle; |
| 28 | + if( $title->getNamespace() == NS_MEDIAWIKI && $title->getText() == 'Gadgets-definition' ) { |
| 29 | + Gadget::loadStructuredList( $text ); |
| 30 | + } |
| 31 | + return true; |
| 32 | + } |
| 33 | + |
| 34 | + /** |
| 35 | + * GetPreferences hook handler. |
| 36 | + * @param $user User |
| 37 | + * @param $preferences Array: Preference descriptions |
| 38 | + */ |
| 39 | + public static function getPreferences( $user, &$preferences ) { |
| 40 | + $gadgets = Gadget::loadStructuredList(); |
| 41 | + if (!$gadgets) return true; |
| 42 | + |
| 43 | + $options = array(); |
| 44 | + $default = array(); |
| 45 | + foreach( $gadgets as $section => $thisSection ) { |
| 46 | + $available = array(); |
| 47 | + foreach( $thisSection as $gadget ) { |
| 48 | + if ( $gadget->isAllowed( $user ) ) { |
| 49 | + $gname = $gadget->getName(); |
| 50 | + $available[$gadget->getDescription()] = $gname; |
| 51 | + if ( $gadget->isEnabled( $user ) ) { |
| 52 | + $default[] = $gname; |
| 53 | + } |
| 54 | + } |
| 55 | + } |
| 56 | + if ( $section !== '' ) { |
| 57 | + $section = wfMsgExt( "gadget-section-$section", 'parseinline' ); |
| 58 | + if ( count ( $available ) ) { |
| 59 | + $options[$section] = $available; |
| 60 | + } |
| 61 | + } else { |
| 62 | + $options = array_merge( $options, $available ); |
| 63 | + } |
| 64 | + } |
| 65 | + |
| 66 | + $preferences['gadgets-intro'] = |
| 67 | + array( |
| 68 | + 'type' => 'info', |
| 69 | + 'label' => ' ', |
| 70 | + 'default' => Xml::tags( 'tr', array(), |
| 71 | + Xml::tags( 'td', array( 'colspan' => 2 ), |
| 72 | + wfMsgExt( 'gadgets-prefstext', 'parse' ) ) ), |
| 73 | + 'section' => 'gadgets', |
| 74 | + 'raw' => 1, |
| 75 | + 'rawrow' => 1, |
| 76 | + ); |
| 77 | + |
| 78 | + $preferences['gadgets'] = |
| 79 | + array( |
| 80 | + 'type' => 'multiselect', |
| 81 | + 'options' => $options, |
| 82 | + 'section' => 'gadgets', |
| 83 | + 'label' => ' ', |
| 84 | + 'prefix' => 'gadget-', |
| 85 | + 'default' => $default, |
| 86 | + ); |
| 87 | + |
| 88 | + return true; |
| 89 | + } |
| 90 | + |
| 91 | + /** |
| 92 | + * ResourceLoaderRegisterModules hook handler. |
| 93 | + * @param $resourceLoader ResourceLoader |
| 94 | + */ |
| 95 | + public static function registerModules( &$resourceLoader ) { |
| 96 | + $gadgets = Gadget::loadList(); |
| 97 | + if ( !$gadgets ) { |
| 98 | + return true; |
| 99 | + } |
| 100 | + foreach ( $gadgets as $g ) { |
| 101 | + $module = $g->getModule(); |
| 102 | + if ( $module ) { |
| 103 | + $resourceLoader->register( $g->getModuleName(), $module ); |
| 104 | + } |
| 105 | + } |
| 106 | + return true; |
| 107 | + } |
| 108 | + |
| 109 | + /** |
| 110 | + * BeforePageDisplay hook handler. |
| 111 | + * @param $out OutputPage |
| 112 | + */ |
| 113 | + public static function beforePageDisplay( $out ) { |
| 114 | + global $wgUser; |
| 115 | + |
| 116 | + wfProfileIn( __METHOD__ ); |
| 117 | + |
| 118 | + $gadgets = Gadget::loadList(); |
| 119 | + if ( !$gadgets ) { |
| 120 | + wfProfileOut( __METHOD__ ); |
| 121 | + return true; |
| 122 | + } |
| 123 | + |
| 124 | + $lb = new LinkBatch(); |
| 125 | + $lb->setCaller( __METHOD__ ); |
| 126 | + $pages = array(); |
| 127 | + |
| 128 | + foreach ( $gadgets as $gadget ) { |
| 129 | + if ( $gadget->isEnabled( $wgUser ) && $gadget->isAllowed( $wgUser ) ) { |
| 130 | + if ( $gadget->hasModule() ) { |
| 131 | + $out->addModules( $gadget->getModuleName() ); |
| 132 | + } |
| 133 | + foreach ( $gadget->getLegacyScripts() as $page ) { |
| 134 | + $lb->add( NS_MEDIAWIKI, $page ); |
| 135 | + $pages[] = $page; |
| 136 | + } |
| 137 | + } |
| 138 | + } |
| 139 | + |
| 140 | + $lb->execute( __METHOD__ ); |
| 141 | + |
| 142 | + $done = array(); |
| 143 | + foreach ( $pages as $page ) { |
| 144 | + if ( isset( $done[$page] ) ) continue; |
| 145 | + $done[$page] = true; |
| 146 | + self::applyScript( $page, $out ); |
| 147 | + } |
| 148 | + wfProfileOut( __METHOD__ ); |
| 149 | + |
| 150 | + return true; |
| 151 | + } |
| 152 | + |
| 153 | + /** |
| 154 | + * Adds one legacy script to output. |
| 155 | + * |
| 156 | + * @param $page String: Unprefixed page title |
| 157 | + * @param $out OutputPage |
| 158 | + */ |
| 159 | + private static function applyScript( $page, $out ) { |
| 160 | + global $wgJsMimeType; |
| 161 | + |
| 162 | + # bug 22929: disable gadgets on sensitive pages. Scripts loaded through the |
| 163 | + # ResourceLoader handle this in OutputPage::getModules() |
| 164 | + # TODO: make this extension load everything via RL, then we don't need to worry |
| 165 | + # about any of this. |
| 166 | + if( $out->getAllowedModules( ResourceLoaderModule::TYPE_SCRIPTS ) < ResourceLoaderModule::ORIGIN_USER_SITEWIDE ){ |
| 167 | + return; |
| 168 | + } |
| 169 | + |
| 170 | + $t = Title::makeTitleSafe( NS_MEDIAWIKI, $page ); |
| 171 | + if ( !$t ) return; |
| 172 | + |
| 173 | + $u = $t->getLocalURL( 'action=raw&ctype=' . $wgJsMimeType ); |
| 174 | + $out->addScriptFile( $u, $t->getLatestRevID() ); |
| 175 | + } |
| 176 | + |
| 177 | + /** |
| 178 | + * UnitTestsList hook handler |
| 179 | + * @param $files Array: List of extension test files |
| 180 | + */ |
| 181 | + public static function unitTestsList( $files ) { |
| 182 | + $files[] = dirname( __FILE__ ) . '/Gadgets_tests.php'; |
| 183 | + return true; |
| 184 | + } |
| 185 | +} |
Property changes on: branches/Gadgets3.0/backend/GadgetHooks.php |
___________________________________________________________________ |
Added: svn:mergeinfo |
1 | 186 | Merged /branches/Gadgets-work/Gadgets_body.php:r73145-76526 |
2 | 187 | Merged /branches/wmf/1.17wmf1/extensions/Gadgets/Gadgets_body.php:r81884 |
Added: svn:eol-style |
3 | 188 | + native |
Added: svn:keywords |
4 | 189 | + LastChangedDate LastChangedRevision |
Index: branches/Gadgets3.0/ui/GadgetsView.php |
— | — | @@ -0,0 +1,25 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +abstract class GadgetsView { |
| 5 | + protected $parent, |
| 6 | + $params; |
| 7 | + |
| 8 | + public function __construct( SpecialGadgets $parent, $params ) { |
| 9 | + $this->parent = $parent; |
| 10 | + $this->params = $params; |
| 11 | + } |
| 12 | + |
| 13 | + public abstract function execute(); |
| 14 | + |
| 15 | + public function post() { |
| 16 | + } |
| 17 | + |
| 18 | + /** |
| 19 | + * @return Message |
| 20 | + */ |
| 21 | + public abstract function getTitle(); |
| 22 | + |
| 23 | + protected function getContext() { |
| 24 | + return $this->parent->getContext(); |
| 25 | + } |
| 26 | +} |
\ No newline at end of file |
Property changes on: branches/Gadgets3.0/ui/GadgetsView.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 27 | + native |
Index: branches/Gadgets3.0/ui/ExportGadgetsView.php |
Property changes on: branches/Gadgets3.0/ui/ExportGadgetsView.php |
___________________________________________________________________ |
Added: svn:eol-style |
2 | 28 | + native |
Index: branches/Gadgets3.0/ui/MainGadgetsView.php |
— | — | @@ -0,0 +1,100 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +class MainGadgetsView extends GadgetsView { |
| 5 | + public function __construct( SpecialGadgets $parent ) { |
| 6 | + parent::__construct( $parent, array() ); |
| 7 | + } |
| 8 | + |
| 9 | + public function execute() { |
| 10 | + global $wgOut, $wgUser, $wgLang, $wgContLang; |
| 11 | + |
| 12 | + $skin = $wgUser->getSkin(); |
| 13 | + |
| 14 | + $wgOut->addWikiMsg( 'gadgets-pagetext' ); |
| 15 | + |
| 16 | + $gadgets = Gadget::loadStructuredList(); |
| 17 | + if ( !$gadgets ) return; |
| 18 | + |
| 19 | + $lang = ""; |
| 20 | + if ( $wgLang->getCode() != $wgContLang->getCode() ) { |
| 21 | + $lang = "/" . $wgLang->getCode(); |
| 22 | + } |
| 23 | + |
| 24 | + $listOpen = false; |
| 25 | + |
| 26 | + $msgOpt = array( 'parseinline', 'parsemag' ); |
| 27 | + $editInterfaceAllowed = $wgUser->isAllowed( 'editinterface' ); |
| 28 | + |
| 29 | + foreach ( $gadgets as $section => $entries ) { |
| 30 | + if ( $section !== false && $section !== '' ) { |
| 31 | + $t = Title::makeTitleSafe( NS_MEDIAWIKI, "Gadget-section-$section$lang" ); |
| 32 | + if ( $editInterfaceAllowed ) { |
| 33 | + $lnkTarget = $t |
| 34 | + ? $skin->link( $t, wfMsgHTML( 'edit' ), array(), array( 'action' => 'edit' ) ) |
| 35 | + : htmlspecialchars( $section ); |
| 36 | + $lnk = "    [$lnkTarget]"; |
| 37 | + } else { |
| 38 | + $lnk = ''; |
| 39 | + } |
| 40 | + $ttext = wfMsgExt( "gadget-section-$section", $msgOpt ); |
| 41 | + |
| 42 | + if( $listOpen ) { |
| 43 | + $wgOut->addHTML( Xml::closeElement( 'ul' ) . "\n" ); |
| 44 | + $listOpen = false; |
| 45 | + } |
| 46 | + $wgOut->addHTML( Html::rawElement( 'h2', array(), $ttext . $lnk ) . "\n" ); |
| 47 | + } |
| 48 | + |
| 49 | + foreach ( $entries as $gadget ) { |
| 50 | + $t = Title::makeTitleSafe( NS_MEDIAWIKI, "Gadget-{$gadget->getName()}$lang" ); |
| 51 | + if ( !$t ) continue; |
| 52 | + |
| 53 | + $links = array(); |
| 54 | + if ( $editInterfaceAllowed ) { |
| 55 | + $links[] = $skin->link( $t, wfMsgHTML( 'edit' ), array(), array( 'action' => 'edit' ) ); |
| 56 | + } |
| 57 | + $links[] = $skin->link( $this->getTitle( "export/{$gadget->getName()}" ), wfMsgHtml( 'gadgets-export' ) ); |
| 58 | + |
| 59 | + $ttext = wfMsgExt( "gadget-{$gadget->getName()}", $msgOpt ); |
| 60 | + |
| 61 | + if( !$listOpen ) { |
| 62 | + $listOpen = true; |
| 63 | + $wgOut->addHTML( Xml::openElement( 'ul' ) ); |
| 64 | + } |
| 65 | + $lnk = '  ' . wfMsg( 'parentheses', $wgLang->pipeList( $links ) ); |
| 66 | + $wgOut->addHTML( Xml::openElement( 'li' ) . |
| 67 | + $ttext . $lnk . "<br />" . |
| 68 | + wfMsgHTML( 'gadgets-uses' ) . wfMsg( 'colon-separator' ) |
| 69 | + ); |
| 70 | + |
| 71 | + $lnk = array(); |
| 72 | + foreach ( $gadget->getScriptsAndStyles() as $codePage ) { |
| 73 | + $t = Title::makeTitleSafe( NS_MEDIAWIKI, $codePage ); |
| 74 | + if ( !$t ) continue; |
| 75 | + |
| 76 | + $lnk[] = $skin->link( $t, htmlspecialchars( $t->getText() ) ); |
| 77 | + } |
| 78 | + $wgOut->addHTML( $wgLang->commaList( $lnk ) ); |
| 79 | + $rights = $gadget->getRequiredRights(); |
| 80 | + if ( count( $rights ) ) { |
| 81 | + $wgOut->addHTML( '<br />' . |
| 82 | + wfMessage( 'gadgets-required-rights', $wgLang->commaList( $rights ), count( $rights ) )->parse() |
| 83 | + ); |
| 84 | + } |
| 85 | + if ( $gadget->isOnByDefault() ) { |
| 86 | + $wgOut->addHTML( '<br />' . wfMessage( 'gadgets-default' )->parse() ); |
| 87 | + } |
| 88 | + |
| 89 | + $wgOut->addHTML( Xml::closeElement( 'li' ) . "\n" ); |
| 90 | + } |
| 91 | + } |
| 92 | + |
| 93 | + if( $listOpen ) { |
| 94 | + $wgOut->addHTML( Xml::closeElement( 'ul' ) . "\n" ); |
| 95 | + } |
| 96 | + } |
| 97 | + |
| 98 | + public function getTitle() { |
| 99 | + return wfMessage( 'gadgets-title' ); |
| 100 | + } |
| 101 | +} |
\ No newline at end of file |
Property changes on: branches/Gadgets3.0/ui/MainGadgetsView.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 102 | + native |
Index: branches/Gadgets3.0/ui/SpecialGadgets.php |
— | — | @@ -31,137 +31,19 @@ |
32 | 32 | * @param $par Parameters passed to the page |
33 | 33 | */ |
34 | 34 | function execute( $par ) { |
35 | | - $parts = explode( '/', $par ); |
36 | | - if ( count( $parts ) == 2 && $parts[0] == 'export' ) { |
37 | | - $this->showExportForm( $parts[1] ); |
38 | | - } else { |
39 | | - $this->showMainForm(); |
40 | | - } |
41 | | - } |
42 | | - |
43 | | - /** |
44 | | - * Displays form showing the list of installed gadgets |
45 | | - */ |
46 | | - public function showMainForm() { |
47 | | - global $wgOut, $wgUser, $wgLang, $wgContLang; |
48 | | - |
49 | | - $skin = $wgUser->getSkin(); |
50 | | - |
| 35 | + // $parts = explode( '/', $par ); |
| 36 | + // if ( count( $parts ) == 2 && $parts[0] == 'export' ) { |
| 37 | + // $this->showExportForm( $parts[1] ); |
| 38 | + // } else { |
| 39 | + $view = new MainGadgetsView( $this ); |
| 40 | + // } |
51 | 41 | $this->setHeaders(); |
52 | | - $wgOut->setPagetitle( wfMsg( "gadgets-title" ) ); |
53 | | - $wgOut->addWikiMsg( 'gadgets-pagetext' ); |
| 42 | + $this->getContext()->getOutput()->setPageTitle( $view->getTitle()->text() ); |
54 | 43 | |
55 | | - $gadgets = Gadget::loadStructuredList(); |
56 | | - if ( !$gadgets ) return; |
57 | | - |
58 | | - $lang = ""; |
59 | | - if ( $wgLang->getCode() != $wgContLang->getCode() ) { |
60 | | - $lang = "/" . $wgLang->getCode(); |
| 44 | + if ( $this->getContext()->getRequest()->wasPosted() ) { |
| 45 | + $view->post(); |
| 46 | + } else { |
| 47 | + $view->execute(); |
61 | 48 | } |
62 | | - |
63 | | - $listOpen = false; |
64 | | - |
65 | | - $msgOpt = array( 'parseinline', 'parsemag' ); |
66 | | - $editInterfaceAllowed = $wgUser->isAllowed( 'editinterface' ); |
67 | | - |
68 | | - foreach ( $gadgets as $section => $entries ) { |
69 | | - if ( $section !== false && $section !== '' ) { |
70 | | - $t = Title::makeTitleSafe( NS_MEDIAWIKI, "Gadget-section-$section$lang" ); |
71 | | - if ( $editInterfaceAllowed ) { |
72 | | - $lnkTarget = $t |
73 | | - ? $skin->link( $t, wfMsgHTML( 'edit' ), array(), array( 'action' => 'edit' ) ) |
74 | | - : htmlspecialchars( $section ); |
75 | | - $lnk = "    [$lnkTarget]"; |
76 | | - } else { |
77 | | - $lnk = ''; |
78 | | - } |
79 | | - $ttext = wfMsgExt( "gadget-section-$section", $msgOpt ); |
80 | | - |
81 | | - if( $listOpen ) { |
82 | | - $wgOut->addHTML( Xml::closeElement( 'ul' ) . "\n" ); |
83 | | - $listOpen = false; |
84 | | - } |
85 | | - $wgOut->addHTML( Html::rawElement( 'h2', array(), $ttext . $lnk ) . "\n" ); |
86 | | - } |
87 | | - |
88 | | - foreach ( $entries as $gadget ) { |
89 | | - $t = Title::makeTitleSafe( NS_MEDIAWIKI, "Gadget-{$gadget->getName()}$lang" ); |
90 | | - if ( !$t ) continue; |
91 | | - |
92 | | - $links = array(); |
93 | | - if ( $editInterfaceAllowed ) { |
94 | | - $links[] = $skin->link( $t, wfMsgHTML( 'edit' ), array(), array( 'action' => 'edit' ) ); |
95 | | - } |
96 | | - $links[] = $skin->link( $this->getTitle( "export/{$gadget->getName()}" ), wfMsgHtml( 'gadgets-export' ) ); |
97 | | - |
98 | | - $ttext = wfMsgExt( "gadget-{$gadget->getName()}", $msgOpt ); |
99 | | - |
100 | | - if( !$listOpen ) { |
101 | | - $listOpen = true; |
102 | | - $wgOut->addHTML( Xml::openElement( 'ul' ) ); |
103 | | - } |
104 | | - $lnk = '  ' . wfMsg( 'parentheses', $wgLang->pipeList( $links ) ); |
105 | | - $wgOut->addHTML( Xml::openElement( 'li' ) . |
106 | | - $ttext . $lnk . "<br />" . |
107 | | - wfMsgHTML( 'gadgets-uses' ) . wfMsg( 'colon-separator' ) |
108 | | - ); |
109 | | - |
110 | | - $lnk = array(); |
111 | | - foreach ( $gadget->getScriptsAndStyles() as $codePage ) { |
112 | | - $t = Title::makeTitleSafe( NS_MEDIAWIKI, $codePage ); |
113 | | - if ( !$t ) continue; |
114 | | - |
115 | | - $lnk[] = $skin->link( $t, htmlspecialchars( $t->getText() ) ); |
116 | | - } |
117 | | - $wgOut->addHTML( $wgLang->commaList( $lnk ) ); |
118 | | - $rights = $gadget->getRequiredRights(); |
119 | | - if ( count( $rights ) ) { |
120 | | - $wgOut->addHTML( '<br />' . |
121 | | - wfMessage( 'gadgets-required-rights', $wgLang->commaList( $rights ), count( $rights ) )->parse() |
122 | | - ); |
123 | | - } |
124 | | - if ( $gadget->isOnByDefault() ) { |
125 | | - $wgOut->addHTML( '<br />' . wfMessage( 'gadgets-default' )->parse() ); |
126 | | - } |
127 | | - |
128 | | - $wgOut->addHTML( Xml::closeElement( 'li' ) . "\n" ); |
129 | | - } |
130 | | - } |
131 | | - |
132 | | - if( $listOpen ) { |
133 | | - $wgOut->addHTML( Xml::closeElement( 'ul' ) . "\n" ); |
134 | | - } |
135 | 49 | } |
136 | | - |
137 | | - /** |
138 | | - * Exports a gadget with its dependencies in a serialized form |
139 | | - * @param $gadget String Name of gadget to export |
140 | | - */ |
141 | | - public function showExportForm( $gadget ) { |
142 | | - global $wgOut, $wgScript; |
143 | | - |
144 | | - $gadgets = Gadget::loadList(); |
145 | | - if ( !isset( $gadgets[$gadget] ) ) { |
146 | | - $wgOut->showErrorPage( 'error', 'gadgets-not-found', array( $gadget ) ); |
147 | | - return; |
148 | | - } |
149 | | - |
150 | | - $g = $gadgets[$gadget]; |
151 | | - $this->setHeaders(); |
152 | | - $wgOut->setPagetitle( wfMsg( "gadgets-export-title" ) ); |
153 | | - $wgOut->addWikiMsg( 'gadgets-export-text', $gadget, $g->getDefinition() ); |
154 | | - |
155 | | - $exportList = "MediaWiki:gadget-$gadget\n"; |
156 | | - foreach ( $g->getScriptsAndStyles() as $page ) { |
157 | | - $exportList .= "MediaWiki:$page\n"; |
158 | | - } |
159 | | - |
160 | | - $wgOut->addHTML( Html::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) ) |
161 | | - . Html::hidden( 'title', SpecialPage::getTitleFor( 'Export' )->getPrefixedDBKey() ) |
162 | | - . Html::hidden( 'pages', $exportList ) |
163 | | - . Html::hidden( 'wpDownload', '1' ) |
164 | | - . Xml::submitButton( wfMsg( 'gadgets-export-download' ) ) |
165 | | - . Html::closeElement( 'form' ) |
166 | | - ); |
167 | | - } |
168 | 50 | } |