Index: branches/Gadgets3.0/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/ApiQueryGadgets.php |
— | — | @@ -1,208 +0,0 @@ |
2 | | -<?php |
3 | | -/** |
4 | | - * Created on 15 April 2011 |
5 | | - * API for Gadgets extension |
6 | | - * |
7 | | - * This program is free software; you can redistribute it and/or modify |
8 | | - * it under the terms of the GNU General Public License as published by |
9 | | - * the Free Software Foundation; either version 2 of the License, or |
10 | | - * (at your option) any later version. |
11 | | - * |
12 | | - * This program is distributed in the hope that it will be useful, |
13 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | | - * GNU General Public License for more details. |
16 | | - * |
17 | | - * You should have received a copy of the GNU General Public License along |
18 | | - * with this program; if not, write to the Free Software Foundation, Inc., |
19 | | - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
20 | | - * http://www.gnu.org/copyleft/gpl.html |
21 | | - */ |
22 | | - |
23 | | -class ApiQueryGadgets extends ApiQueryBase { |
24 | | - private $props, |
25 | | - $category, |
26 | | - $neededNames, |
27 | | - $listAllowed, |
28 | | - $listEnabled; |
29 | | - |
30 | | - public function __construct( $query, $moduleName ) { |
31 | | - parent::__construct( $query, $moduleName, 'ga' ); |
32 | | - } |
33 | | - |
34 | | - public function execute() { |
35 | | - $params = $this->extractRequestParams(); |
36 | | - $this->props = array_flip( $params['prop'] ); |
37 | | - $this->categories = isset( $params['categories'] ) |
38 | | - ? array_flip( $params['categories'] ) |
39 | | - : false; |
40 | | - $this->neededNames = isset( $params['names'] ) |
41 | | - ? array_flip( $params['names'] ) |
42 | | - : false; |
43 | | - $this->listAllowed = isset( $params['allowed'] ) && $params['allowed']; |
44 | | - $this->listEnabled = isset( $params['enabled'] ) && $params['enabled']; |
45 | | - |
46 | | - $this->getMain()->setCacheMode( $this->listAllowed || $this->listEnabled |
47 | | - ? 'anon-public-user-private' : 'public' ); |
48 | | - |
49 | | - $this->applyList( $this->getList() ); |
50 | | - } |
51 | | - |
52 | | - private function getList() { |
53 | | - $gadgets = Gadget::loadStructuredList(); |
54 | | - |
55 | | - $result = array(); |
56 | | - foreach ( $gadgets as $category => $list ) { |
57 | | - if ( $this->categories && !isset( $this->categories[$category] ) ) { |
58 | | - continue; |
59 | | - } |
60 | | - foreach ( $list as $g ) { |
61 | | - if ( $this->isNeeded( $g ) ) { |
62 | | - $result[] = $g; |
63 | | - } |
64 | | - } |
65 | | - } |
66 | | - return $result; |
67 | | - } |
68 | | - |
69 | | - private function applyList( $gadgets ) { |
70 | | - $data = array(); |
71 | | - $result = $this->getResult(); |
72 | | - |
73 | | - foreach ( $gadgets as $g ) { |
74 | | - $row = array(); |
75 | | - if ( isset( $this->props['name'] ) ) { |
76 | | - $row['name'] = $g->getName(); |
77 | | - } |
78 | | - if ( isset( $this->props['desc'] ) ) { |
79 | | - $row['desc'] = $g->getDescription(); |
80 | | - } |
81 | | - if ( isset( $this->props['desc-raw'] ) ) { |
82 | | - $row['desc-raw'] = $g->getRawDescription(); |
83 | | - } |
84 | | - if ( isset( $this->props['category'] ) ) { |
85 | | - $row['category'] = $g->getCategory(); |
86 | | - } |
87 | | - if ( isset( $this->props['resourceloader'] ) && $g->supportsResourceLoader() ) { |
88 | | - $row['resourceloader'] = ''; |
89 | | - } |
90 | | - if ( isset( $this->props['scripts'] ) ) { |
91 | | - $row['scripts'] = $g->getScripts(); |
92 | | - $result->setIndexedTagName( $row['scripts'], 'script' ); |
93 | | - } |
94 | | - if ( isset( $this->props['styles'] ) ) { |
95 | | - $row['styles'] = $g->getStyles(); |
96 | | - $result->setIndexedTagName( $row['styles'], 'style' ); |
97 | | - } |
98 | | - if ( isset( $this->props['dependencies'] ) ) { |
99 | | - $row['dependencies'] = $g->getDependencies(); |
100 | | - $result->setIndexedTagName( $row['dependencies'], 'module' ); |
101 | | - } |
102 | | - if ( isset( $this->props['rights'] ) ) { |
103 | | - $row['rights'] = $g->getRequiredRights(); |
104 | | - $result->setIndexedTagName( $row['rights'], 'right' ); |
105 | | - } |
106 | | - if ( isset( $this->props['default'] ) && $g->isOnByDefault() ) { |
107 | | - $row['default'] = ''; |
108 | | - } |
109 | | - if ( isset( $this->props['definition'] ) ) { |
110 | | - $row['definition'] = $g->getDefinition(); |
111 | | - } |
112 | | - $data[] = $row; |
113 | | - } |
114 | | - $result->setIndexedTagName( $data, 'gadget' ); |
115 | | - $result->addValue( 'query', $this->getModuleName(), $data ); |
116 | | - } |
117 | | - |
118 | | - /** |
119 | | - * |
120 | | - */ |
121 | | - private function isNeeded( Gadget $gadget ) { |
122 | | - global $wgUser; |
123 | | - |
124 | | - return ( $this->neededNames === false || isset( $this->neededNames[$gadget->getName()] ) ) |
125 | | - && ( !$this->listAllowed || $gadget->isAllowed( $wgUser ) ) |
126 | | - && ( !$this->listEnabled || $gadget->isEnabled( $wgUser ) ); |
127 | | - } |
128 | | - |
129 | | - public function getAllowedParams() { |
130 | | - return array( |
131 | | - 'prop' => array( |
132 | | - ApiBase::PARAM_DFLT => 'name', |
133 | | - ApiBase::PARAM_ISMULTI => true, |
134 | | - ApiBase::PARAM_TYPE => array( |
135 | | - 'name', |
136 | | - 'desc', |
137 | | - 'desc-raw', |
138 | | - 'category', |
139 | | - 'resourceloader', |
140 | | - 'scripts', |
141 | | - 'styles', |
142 | | - 'dependencies', |
143 | | - 'rights', |
144 | | - 'default', |
145 | | - 'definition', |
146 | | - ), |
147 | | - ), |
148 | | - 'categories' => array( |
149 | | - ApiBase::PARAM_ISMULTI => true, |
150 | | - ApiBase::PARAM_TYPE => 'string', |
151 | | - ), |
152 | | - 'names' => array( |
153 | | - ApiBase::PARAM_TYPE => 'string', |
154 | | - ApiBase::PARAM_ISMULTI => true, |
155 | | - ), |
156 | | - 'allowed' => false, |
157 | | - 'enabled' => false, |
158 | | - ); |
159 | | - } |
160 | | - |
161 | | - public function getDescription() { |
162 | | - return 'Returns a list of gadgets used on this wiki'; |
163 | | - } |
164 | | - |
165 | | - public function getParamDescription() { |
166 | | - return array( |
167 | | - 'prop' => array( |
168 | | - 'What gadget information to get:', |
169 | | - ' name - Internal gadget name', |
170 | | - ' desc - Gadget description transformed into HTML (can be slow, use only if really needed)', |
171 | | - ' desc-raw - Gadget description in raw wikitext', |
172 | | - ' category - Internal name of a category gadget belongs to (empty if top-level gadget)', |
173 | | - ' resourceloader - Whether gadget supports ResourceLoader', |
174 | | - " scripts - List of gadget's scripts", |
175 | | - " styles - List of gadget's styles", |
176 | | - ' dependencies - List of ResourceLoader modules gadget depends on', |
177 | | - ' rights - List of rights required to use gadget, if any', |
178 | | - ' default - Whether gadget is enabled by default', |
179 | | - ' definition - Line from MediaWiki:Gadgets-definition used to define the gadget', |
180 | | - ), |
181 | | - 'categories' => 'Gadgets from what categories to retrieve', |
182 | | - 'names' => 'Name(s) of gadgets to retrieve', |
183 | | - 'allowed' => 'List only gadgets allowed to current user', |
184 | | - 'enabled' => 'List only gadgets enabled by current user', |
185 | | - ); |
186 | | - } |
187 | | - |
188 | | - protected function getExamples() { |
189 | | - $params = $this->getAllowedParams(); |
190 | | - $allProps = implode( '|', $params['prop'][ApiBase::PARAM_TYPE] ); |
191 | | - return array( |
192 | | - 'Get a list of gadgets along with their descriptions:', |
193 | | - ' api.php?action=query&list=gadgets&gaprop=name|desc', |
194 | | - 'Get a list of gadgets with all possble properties:', |
195 | | - " api.php?action=query&list=gadgets&gaprop=$allProps", |
196 | | - 'Get a list of gadgets belonging to caregory "foo":', |
197 | | - ' api.php?action=query&list=gadgets&gacategories=foo', |
198 | | - 'Get information about gadgets named "foo" and "bar":', |
199 | | - ' api.php?action=query&list=gadgets&ganames=foo|bar&gaprop=name|desc|category', |
200 | | - 'Get a list of gadgets enabled by current user:', |
201 | | - ' api.php?action=query&list=gadgets&gaenabled', |
202 | | - ); |
203 | | - } |
204 | | - |
205 | | - public function getVersion() { |
206 | | - return __CLASS__ . ': $Id$'; |
207 | | - } |
208 | | - |
209 | | -} |
Index: branches/Gadgets3.0/SpecialGadgets.php |
— | — | @@ -1,167 +0,0 @@ |
2 | | -<?php |
3 | | -/** |
4 | | - * Special:Gadgets, provides a preview of MediaWiki:Gadgets. |
5 | | - * |
6 | | - * @file |
7 | | - * @ingroup SpecialPage |
8 | | - * @author Daniel Kinzler, brightbyte.de |
9 | | - * @copyright © 2007 Daniel Kinzler |
10 | | - * @license GNU General Public License 2.0 or later |
11 | | - */ |
12 | | - |
13 | | -if( !defined( 'MEDIAWIKI' ) ) { |
14 | | - echo( "not a valid entry point.\n" ); |
15 | | - die( 1 ); |
16 | | -} |
17 | | - |
18 | | -/** |
19 | | - * |
20 | | - */ |
21 | | -class SpecialGadgets extends SpecialPage { |
22 | | - |
23 | | - /** |
24 | | - * Constructor |
25 | | - */ |
26 | | - function __construct() { |
27 | | - parent::__construct( 'Gadgets', '', true ); |
28 | | - } |
29 | | - |
30 | | - /** |
31 | | - * Main execution function |
32 | | - * @param $par Parameters passed to the page |
33 | | - */ |
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 | | - |
51 | | - $this->setHeaders(); |
52 | | - $wgOut->setPagetitle( wfMsg( "gadgets-title" ) ); |
53 | | - $wgOut->addWikiMsg( 'gadgets-pagetext' ); |
54 | | - |
55 | | - $gadgets = Gadget::loadStructuredList(); |
56 | | - if ( !$gadgets ) return; |
57 | | - |
58 | | - $lang = ""; |
59 | | - if ( $wgLang->getCode() != $wgContLang->getCode() ) { |
60 | | - $lang = "/" . $wgLang->getCode(); |
61 | | - } |
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 | | - } |
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 | | -} |
Index: branches/Gadgets3.0/ApiQueryGadgetCategories.php |
— | — | @@ -1,122 +0,0 @@ |
2 | | -<?php |
3 | | -/** |
4 | | - * Created on 16 April 2011 |
5 | | - * API for Gadgets extension |
6 | | - * |
7 | | - * This program is free software; you can redistribute it and/or modify |
8 | | - * it under the terms of the GNU General Public License as published by |
9 | | - * the Free Software Foundation; either version 2 of the License, or |
10 | | - * (at your option) any later version. |
11 | | - * |
12 | | - * This program is distributed in the hope that it will be useful, |
13 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | | - * GNU General Public License for more details. |
16 | | - * |
17 | | - * You should have received a copy of the GNU General Public License along |
18 | | - * with this program; if not, write to the Free Software Foundation, Inc., |
19 | | - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
20 | | - * http://www.gnu.org/copyleft/gpl.html |
21 | | - */ |
22 | | - |
23 | | -class ApiQueryGadgetCategories extends ApiQueryBase { |
24 | | - private $props, |
25 | | - $neededNames; |
26 | | - |
27 | | - public function __construct( $query, $moduleName ) { |
28 | | - parent::__construct( $query, $moduleName, 'gc' ); |
29 | | - } |
30 | | - |
31 | | - public function execute() { |
32 | | - $params = $this->extractRequestParams(); |
33 | | - $this->props = array_flip( $params['prop'] ); |
34 | | - $this->neededNames = isset( $params['names'] ) |
35 | | - ? array_flip( $params['names'] ) |
36 | | - : false; |
37 | | - |
38 | | - $this->getMain()->setCacheMode( 'public' ); |
39 | | - |
40 | | - $this->getList(); |
41 | | - } |
42 | | - |
43 | | - private function getList() { |
44 | | - $data = array(); |
45 | | - $result = $this->getResult(); |
46 | | - $gadgets = Gadget::loadStructuredList(); |
47 | | - |
48 | | - foreach ( $gadgets as $category => $list ) { |
49 | | - if ( !$this->neededNames || isset( $this->neededNames[$category] ) ) { |
50 | | - $row = array(); |
51 | | - if ( isset( $this->props['name'] ) ) { |
52 | | - $row['name'] = $category; |
53 | | - } |
54 | | - if ( $category !== "" ) { |
55 | | - if ( isset( $this->props['desc'] ) ) { |
56 | | - $row['desc'] = wfMessage( "gadget-section-$category" )->parse(); |
57 | | - } |
58 | | - if ( isset( $this->props['desc-raw'] ) ) { |
59 | | - $row['desc-raw'] = wfMessage( "gadget-section-$category" )->plain(); |
60 | | - } |
61 | | - } |
62 | | - if ( isset( $this->props['members'] ) ) { |
63 | | - $row['members'] = count( $list ); |
64 | | - } |
65 | | - $data[] = $row; |
66 | | - } |
67 | | - } |
68 | | - $result->setIndexedTagName( $data, 'category' ); |
69 | | - $result->addValue( 'query', $this->getModuleName(), $data ); |
70 | | - } |
71 | | - |
72 | | - public function getAllowedParams() { |
73 | | - return array( |
74 | | - 'prop' => array( |
75 | | - ApiBase::PARAM_DFLT => 'name', |
76 | | - ApiBase::PARAM_ISMULTI => true, |
77 | | - ApiBase::PARAM_TYPE => array( |
78 | | - 'name', |
79 | | - 'desc', |
80 | | - 'desc-raw', |
81 | | - 'members', |
82 | | - ), |
83 | | - ), |
84 | | - 'names' => array( |
85 | | - ApiBase::PARAM_TYPE => 'string', |
86 | | - ApiBase::PARAM_ISMULTI => true, |
87 | | - ), |
88 | | - ); |
89 | | - } |
90 | | - |
91 | | - public function getDescription() { |
92 | | - return 'Returns a list of gadget categories'; |
93 | | - } |
94 | | - |
95 | | - public function getParamDescription() { |
96 | | - return array( |
97 | | - 'prop' => array( |
98 | | - 'What gadget category information to get:', |
99 | | - ' name - Internal category name', |
100 | | - ' desc - Category description transformed into HTML (can be slow, use only if really needed)', |
101 | | - ' desc-raw - Category description in raw wikitext', |
102 | | - ' members - Number of gadgets in category', |
103 | | - ), |
104 | | - 'names' => 'Name(s) of gadgets to retrieve', |
105 | | - ); |
106 | | - } |
107 | | - |
108 | | - protected function getExamples() { |
109 | | - $params = $this->getAllowedParams(); |
110 | | - $allProps = implode( '|', $params['prop'][ApiBase::PARAM_TYPE] ); |
111 | | - return array( |
112 | | - 'Get a list of existing gadget categories:', |
113 | | - ' api.php?action=query&list=gadgetcategories', |
114 | | - 'Get all information about categories named "foo" and "bar":', |
115 | | - " api.php?action=query&list=gadgetcategories&gcnames=foo|bar&gcprop=$allProps", |
116 | | - ); |
117 | | - } |
118 | | - |
119 | | - public function getVersion() { |
120 | | - return __CLASS__ . ': $Id$'; |
121 | | - } |
122 | | - |
123 | | -} |
Index: branches/Gadgets3.0/Gadgets.php |
— | — | @@ -39,12 +39,12 @@ |
40 | 40 | $wgExtensionMessagesFiles['Gadgets'] = $dir . 'Gadgets.i18n.php'; |
41 | 41 | $wgExtensionAliasesFiles['Gadgets'] = $dir . 'Gadgets.alias.php'; |
42 | 42 | |
43 | | -$wgAutoloadClasses['ApiQueryGadgetCategories'] = $dir . 'ApiQueryGadgetCategories.php'; |
44 | | -$wgAutoloadClasses['ApiQueryGadgets'] = $dir . 'ApiQueryGadgets.php'; |
45 | | -$wgAutoloadClasses['Gadget'] = $dir . 'Gadgets_body.php'; |
46 | | -$wgAutoloadClasses['GadgetHooks'] = $dir . 'Gadgets_body.php'; |
47 | | -$wgAutoloadClasses['GadgetResourceLoaderModule'] = $dir . 'Gadgets_body.php'; |
48 | | -$wgAutoloadClasses['SpecialGadgets'] = $dir . 'SpecialGadgets.php'; |
| 43 | +$wgAutoloadClasses['ApiQueryGadgetCategories'] = $dir . 'api/ApiQueryGadgetCategories.php'; |
| 44 | +$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'; |
| 48 | +$wgAutoloadClasses['SpecialGadgets'] = $dir . 'ui/SpecialGadgets.php'; |
49 | 49 | |
50 | 50 | $wgSpecialPages['Gadgets'] = 'SpecialGadgets'; |
51 | 51 | $wgSpecialPageGroups['Gadgets'] = 'wiki'; |
Index: branches/Gadgets3.0/backend/Gadgets_body.php |
— | — | @@ -0,0 +1,567 @@ |
| 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 | +} |
Property changes on: branches/Gadgets3.0/backend/Gadgets_body.php |
___________________________________________________________________ |
Added: svn:keywords |
1 | 569 | + LastChangedDate LastChangedRevision |
Added: svn:mergeinfo |
2 | 570 | Merged /branches/Gadgets-work/Gadgets_body.php:r73145-76526 |
3 | 571 | Merged /branches/wmf/1.17wmf1/extensions/Gadgets/Gadgets_body.php:r81884 |
Added: svn:eol-style |
4 | 572 | + native |
Index: branches/Gadgets3.0/api/ApiQueryGadgets.php |
— | — | @@ -0,0 +1,208 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Created on 15 April 2011 |
| 5 | + * API for Gadgets extension |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or modify |
| 8 | + * it under the terms of the GNU General Public License as published by |
| 9 | + * the Free Software Foundation; either version 2 of the License, or |
| 10 | + * (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU General Public License along |
| 18 | + * with this program; if not, write to the Free Software Foundation, Inc., |
| 19 | + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| 20 | + * http://www.gnu.org/copyleft/gpl.html |
| 21 | + */ |
| 22 | + |
| 23 | +class ApiQueryGadgets extends ApiQueryBase { |
| 24 | + private $props, |
| 25 | + $category, |
| 26 | + $neededNames, |
| 27 | + $listAllowed, |
| 28 | + $listEnabled; |
| 29 | + |
| 30 | + public function __construct( $query, $moduleName ) { |
| 31 | + parent::__construct( $query, $moduleName, 'ga' ); |
| 32 | + } |
| 33 | + |
| 34 | + public function execute() { |
| 35 | + $params = $this->extractRequestParams(); |
| 36 | + $this->props = array_flip( $params['prop'] ); |
| 37 | + $this->categories = isset( $params['categories'] ) |
| 38 | + ? array_flip( $params['categories'] ) |
| 39 | + : false; |
| 40 | + $this->neededNames = isset( $params['names'] ) |
| 41 | + ? array_flip( $params['names'] ) |
| 42 | + : false; |
| 43 | + $this->listAllowed = isset( $params['allowed'] ) && $params['allowed']; |
| 44 | + $this->listEnabled = isset( $params['enabled'] ) && $params['enabled']; |
| 45 | + |
| 46 | + $this->getMain()->setCacheMode( $this->listAllowed || $this->listEnabled |
| 47 | + ? 'anon-public-user-private' : 'public' ); |
| 48 | + |
| 49 | + $this->applyList( $this->getList() ); |
| 50 | + } |
| 51 | + |
| 52 | + private function getList() { |
| 53 | + $gadgets = Gadget::loadStructuredList(); |
| 54 | + |
| 55 | + $result = array(); |
| 56 | + foreach ( $gadgets as $category => $list ) { |
| 57 | + if ( $this->categories && !isset( $this->categories[$category] ) ) { |
| 58 | + continue; |
| 59 | + } |
| 60 | + foreach ( $list as $g ) { |
| 61 | + if ( $this->isNeeded( $g ) ) { |
| 62 | + $result[] = $g; |
| 63 | + } |
| 64 | + } |
| 65 | + } |
| 66 | + return $result; |
| 67 | + } |
| 68 | + |
| 69 | + private function applyList( $gadgets ) { |
| 70 | + $data = array(); |
| 71 | + $result = $this->getResult(); |
| 72 | + |
| 73 | + foreach ( $gadgets as $g ) { |
| 74 | + $row = array(); |
| 75 | + if ( isset( $this->props['name'] ) ) { |
| 76 | + $row['name'] = $g->getName(); |
| 77 | + } |
| 78 | + if ( isset( $this->props['desc'] ) ) { |
| 79 | + $row['desc'] = $g->getDescription(); |
| 80 | + } |
| 81 | + if ( isset( $this->props['desc-raw'] ) ) { |
| 82 | + $row['desc-raw'] = $g->getRawDescription(); |
| 83 | + } |
| 84 | + if ( isset( $this->props['category'] ) ) { |
| 85 | + $row['category'] = $g->getCategory(); |
| 86 | + } |
| 87 | + if ( isset( $this->props['resourceloader'] ) && $g->supportsResourceLoader() ) { |
| 88 | + $row['resourceloader'] = ''; |
| 89 | + } |
| 90 | + if ( isset( $this->props['scripts'] ) ) { |
| 91 | + $row['scripts'] = $g->getScripts(); |
| 92 | + $result->setIndexedTagName( $row['scripts'], 'script' ); |
| 93 | + } |
| 94 | + if ( isset( $this->props['styles'] ) ) { |
| 95 | + $row['styles'] = $g->getStyles(); |
| 96 | + $result->setIndexedTagName( $row['styles'], 'style' ); |
| 97 | + } |
| 98 | + if ( isset( $this->props['dependencies'] ) ) { |
| 99 | + $row['dependencies'] = $g->getDependencies(); |
| 100 | + $result->setIndexedTagName( $row['dependencies'], 'module' ); |
| 101 | + } |
| 102 | + if ( isset( $this->props['rights'] ) ) { |
| 103 | + $row['rights'] = $g->getRequiredRights(); |
| 104 | + $result->setIndexedTagName( $row['rights'], 'right' ); |
| 105 | + } |
| 106 | + if ( isset( $this->props['default'] ) && $g->isOnByDefault() ) { |
| 107 | + $row['default'] = ''; |
| 108 | + } |
| 109 | + if ( isset( $this->props['definition'] ) ) { |
| 110 | + $row['definition'] = $g->getDefinition(); |
| 111 | + } |
| 112 | + $data[] = $row; |
| 113 | + } |
| 114 | + $result->setIndexedTagName( $data, 'gadget' ); |
| 115 | + $result->addValue( 'query', $this->getModuleName(), $data ); |
| 116 | + } |
| 117 | + |
| 118 | + /** |
| 119 | + * |
| 120 | + */ |
| 121 | + private function isNeeded( Gadget $gadget ) { |
| 122 | + global $wgUser; |
| 123 | + |
| 124 | + return ( $this->neededNames === false || isset( $this->neededNames[$gadget->getName()] ) ) |
| 125 | + && ( !$this->listAllowed || $gadget->isAllowed( $wgUser ) ) |
| 126 | + && ( !$this->listEnabled || $gadget->isEnabled( $wgUser ) ); |
| 127 | + } |
| 128 | + |
| 129 | + public function getAllowedParams() { |
| 130 | + return array( |
| 131 | + 'prop' => array( |
| 132 | + ApiBase::PARAM_DFLT => 'name', |
| 133 | + ApiBase::PARAM_ISMULTI => true, |
| 134 | + ApiBase::PARAM_TYPE => array( |
| 135 | + 'name', |
| 136 | + 'desc', |
| 137 | + 'desc-raw', |
| 138 | + 'category', |
| 139 | + 'resourceloader', |
| 140 | + 'scripts', |
| 141 | + 'styles', |
| 142 | + 'dependencies', |
| 143 | + 'rights', |
| 144 | + 'default', |
| 145 | + 'definition', |
| 146 | + ), |
| 147 | + ), |
| 148 | + 'categories' => array( |
| 149 | + ApiBase::PARAM_ISMULTI => true, |
| 150 | + ApiBase::PARAM_TYPE => 'string', |
| 151 | + ), |
| 152 | + 'names' => array( |
| 153 | + ApiBase::PARAM_TYPE => 'string', |
| 154 | + ApiBase::PARAM_ISMULTI => true, |
| 155 | + ), |
| 156 | + 'allowed' => false, |
| 157 | + 'enabled' => false, |
| 158 | + ); |
| 159 | + } |
| 160 | + |
| 161 | + public function getDescription() { |
| 162 | + return 'Returns a list of gadgets used on this wiki'; |
| 163 | + } |
| 164 | + |
| 165 | + public function getParamDescription() { |
| 166 | + return array( |
| 167 | + 'prop' => array( |
| 168 | + 'What gadget information to get:', |
| 169 | + ' name - Internal gadget name', |
| 170 | + ' desc - Gadget description transformed into HTML (can be slow, use only if really needed)', |
| 171 | + ' desc-raw - Gadget description in raw wikitext', |
| 172 | + ' category - Internal name of a category gadget belongs to (empty if top-level gadget)', |
| 173 | + ' resourceloader - Whether gadget supports ResourceLoader', |
| 174 | + " scripts - List of gadget's scripts", |
| 175 | + " styles - List of gadget's styles", |
| 176 | + ' dependencies - List of ResourceLoader modules gadget depends on', |
| 177 | + ' rights - List of rights required to use gadget, if any', |
| 178 | + ' default - Whether gadget is enabled by default', |
| 179 | + ' definition - Line from MediaWiki:Gadgets-definition used to define the gadget', |
| 180 | + ), |
| 181 | + 'categories' => 'Gadgets from what categories to retrieve', |
| 182 | + 'names' => 'Name(s) of gadgets to retrieve', |
| 183 | + 'allowed' => 'List only gadgets allowed to current user', |
| 184 | + 'enabled' => 'List only gadgets enabled by current user', |
| 185 | + ); |
| 186 | + } |
| 187 | + |
| 188 | + protected function getExamples() { |
| 189 | + $params = $this->getAllowedParams(); |
| 190 | + $allProps = implode( '|', $params['prop'][ApiBase::PARAM_TYPE] ); |
| 191 | + return array( |
| 192 | + 'Get a list of gadgets along with their descriptions:', |
| 193 | + ' api.php?action=query&list=gadgets&gaprop=name|desc', |
| 194 | + 'Get a list of gadgets with all possble properties:', |
| 195 | + " api.php?action=query&list=gadgets&gaprop=$allProps", |
| 196 | + 'Get a list of gadgets belonging to caregory "foo":', |
| 197 | + ' api.php?action=query&list=gadgets&gacategories=foo', |
| 198 | + 'Get information about gadgets named "foo" and "bar":', |
| 199 | + ' api.php?action=query&list=gadgets&ganames=foo|bar&gaprop=name|desc|category', |
| 200 | + 'Get a list of gadgets enabled by current user:', |
| 201 | + ' api.php?action=query&list=gadgets&gaenabled', |
| 202 | + ); |
| 203 | + } |
| 204 | + |
| 205 | + public function getVersion() { |
| 206 | + return __CLASS__ . ': $Id$'; |
| 207 | + } |
| 208 | + |
| 209 | +} |
Property changes on: branches/Gadgets3.0/api/ApiQueryGadgets.php |
___________________________________________________________________ |
Added: svn:keywords |
1 | 210 | + Id |
Added: svn:eol-style |
2 | 211 | + native |
Index: branches/Gadgets3.0/api/ApiQueryGadgetCategories.php |
— | — | @@ -0,0 +1,122 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Created on 16 April 2011 |
| 5 | + * API for Gadgets extension |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or modify |
| 8 | + * it under the terms of the GNU General Public License as published by |
| 9 | + * the Free Software Foundation; either version 2 of the License, or |
| 10 | + * (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU General Public License along |
| 18 | + * with this program; if not, write to the Free Software Foundation, Inc., |
| 19 | + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| 20 | + * http://www.gnu.org/copyleft/gpl.html |
| 21 | + */ |
| 22 | + |
| 23 | +class ApiQueryGadgetCategories extends ApiQueryBase { |
| 24 | + private $props, |
| 25 | + $neededNames; |
| 26 | + |
| 27 | + public function __construct( $query, $moduleName ) { |
| 28 | + parent::__construct( $query, $moduleName, 'gc' ); |
| 29 | + } |
| 30 | + |
| 31 | + public function execute() { |
| 32 | + $params = $this->extractRequestParams(); |
| 33 | + $this->props = array_flip( $params['prop'] ); |
| 34 | + $this->neededNames = isset( $params['names'] ) |
| 35 | + ? array_flip( $params['names'] ) |
| 36 | + : false; |
| 37 | + |
| 38 | + $this->getMain()->setCacheMode( 'public' ); |
| 39 | + |
| 40 | + $this->getList(); |
| 41 | + } |
| 42 | + |
| 43 | + private function getList() { |
| 44 | + $data = array(); |
| 45 | + $result = $this->getResult(); |
| 46 | + $gadgets = Gadget::loadStructuredList(); |
| 47 | + |
| 48 | + foreach ( $gadgets as $category => $list ) { |
| 49 | + if ( !$this->neededNames || isset( $this->neededNames[$category] ) ) { |
| 50 | + $row = array(); |
| 51 | + if ( isset( $this->props['name'] ) ) { |
| 52 | + $row['name'] = $category; |
| 53 | + } |
| 54 | + if ( $category !== "" ) { |
| 55 | + if ( isset( $this->props['desc'] ) ) { |
| 56 | + $row['desc'] = wfMessage( "gadget-section-$category" )->parse(); |
| 57 | + } |
| 58 | + if ( isset( $this->props['desc-raw'] ) ) { |
| 59 | + $row['desc-raw'] = wfMessage( "gadget-section-$category" )->plain(); |
| 60 | + } |
| 61 | + } |
| 62 | + if ( isset( $this->props['members'] ) ) { |
| 63 | + $row['members'] = count( $list ); |
| 64 | + } |
| 65 | + $data[] = $row; |
| 66 | + } |
| 67 | + } |
| 68 | + $result->setIndexedTagName( $data, 'category' ); |
| 69 | + $result->addValue( 'query', $this->getModuleName(), $data ); |
| 70 | + } |
| 71 | + |
| 72 | + public function getAllowedParams() { |
| 73 | + return array( |
| 74 | + 'prop' => array( |
| 75 | + ApiBase::PARAM_DFLT => 'name', |
| 76 | + ApiBase::PARAM_ISMULTI => true, |
| 77 | + ApiBase::PARAM_TYPE => array( |
| 78 | + 'name', |
| 79 | + 'desc', |
| 80 | + 'desc-raw', |
| 81 | + 'members', |
| 82 | + ), |
| 83 | + ), |
| 84 | + 'names' => array( |
| 85 | + ApiBase::PARAM_TYPE => 'string', |
| 86 | + ApiBase::PARAM_ISMULTI => true, |
| 87 | + ), |
| 88 | + ); |
| 89 | + } |
| 90 | + |
| 91 | + public function getDescription() { |
| 92 | + return 'Returns a list of gadget categories'; |
| 93 | + } |
| 94 | + |
| 95 | + public function getParamDescription() { |
| 96 | + return array( |
| 97 | + 'prop' => array( |
| 98 | + 'What gadget category information to get:', |
| 99 | + ' name - Internal category name', |
| 100 | + ' desc - Category description transformed into HTML (can be slow, use only if really needed)', |
| 101 | + ' desc-raw - Category description in raw wikitext', |
| 102 | + ' members - Number of gadgets in category', |
| 103 | + ), |
| 104 | + 'names' => 'Name(s) of gadgets to retrieve', |
| 105 | + ); |
| 106 | + } |
| 107 | + |
| 108 | + protected function getExamples() { |
| 109 | + $params = $this->getAllowedParams(); |
| 110 | + $allProps = implode( '|', $params['prop'][ApiBase::PARAM_TYPE] ); |
| 111 | + return array( |
| 112 | + 'Get a list of existing gadget categories:', |
| 113 | + ' api.php?action=query&list=gadgetcategories', |
| 114 | + 'Get all information about categories named "foo" and "bar":', |
| 115 | + " api.php?action=query&list=gadgetcategories&gcnames=foo|bar&gcprop=$allProps", |
| 116 | + ); |
| 117 | + } |
| 118 | + |
| 119 | + public function getVersion() { |
| 120 | + return __CLASS__ . ': $Id$'; |
| 121 | + } |
| 122 | + |
| 123 | +} |
Property changes on: branches/Gadgets3.0/api/ApiQueryGadgetCategories.php |
___________________________________________________________________ |
Added: svn:keywords |
1 | 124 | + Id |
Added: svn:eol-style |
2 | 125 | + native |
Index: branches/Gadgets3.0/ui/SpecialGadgets.php |
— | — | @@ -0,0 +1,167 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Special:Gadgets, provides a preview of MediaWiki:Gadgets. |
| 5 | + * |
| 6 | + * @file |
| 7 | + * @ingroup SpecialPage |
| 8 | + * @author Daniel Kinzler, brightbyte.de |
| 9 | + * @copyright © 2007 Daniel Kinzler |
| 10 | + * @license GNU General Public License 2.0 or later |
| 11 | + */ |
| 12 | + |
| 13 | +if( !defined( 'MEDIAWIKI' ) ) { |
| 14 | + echo( "not a valid entry point.\n" ); |
| 15 | + die( 1 ); |
| 16 | +} |
| 17 | + |
| 18 | +/** |
| 19 | + * |
| 20 | + */ |
| 21 | +class SpecialGadgets extends SpecialPage { |
| 22 | + |
| 23 | + /** |
| 24 | + * Constructor |
| 25 | + */ |
| 26 | + function __construct() { |
| 27 | + parent::__construct( 'Gadgets', '', true ); |
| 28 | + } |
| 29 | + |
| 30 | + /** |
| 31 | + * Main execution function |
| 32 | + * @param $par Parameters passed to the page |
| 33 | + */ |
| 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 | + |
| 51 | + $this->setHeaders(); |
| 52 | + $wgOut->setPagetitle( wfMsg( "gadgets-title" ) ); |
| 53 | + $wgOut->addWikiMsg( 'gadgets-pagetext' ); |
| 54 | + |
| 55 | + $gadgets = Gadget::loadStructuredList(); |
| 56 | + if ( !$gadgets ) return; |
| 57 | + |
| 58 | + $lang = ""; |
| 59 | + if ( $wgLang->getCode() != $wgContLang->getCode() ) { |
| 60 | + $lang = "/" . $wgLang->getCode(); |
| 61 | + } |
| 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 | + } |
| 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 | +} |
Property changes on: branches/Gadgets3.0/ui/SpecialGadgets.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 169 | + native |