r86393 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r86392‎ | r86393 | r86394 >
Date:13:39, 19 April 2011
Author:maxsem
Status:ok
Tags:
Comment:
Rearranged code to use subdirectories
Modified paths:
  • /branches/Gadgets3.0/ApiQueryGadgetCategories.php (deleted) (history)
  • /branches/Gadgets3.0/ApiQueryGadgets.php (deleted) (history)
  • /branches/Gadgets3.0/Gadgets.php (modified) (history)
  • /branches/Gadgets3.0/Gadgets_body.php (deleted) (history)
  • /branches/Gadgets3.0/SpecialGadgets.php (deleted) (history)
  • /branches/Gadgets3.0/api (added) (history)
  • /branches/Gadgets3.0/api/ApiQueryGadgetCategories.php (added) (history)
  • /branches/Gadgets3.0/api/ApiQueryGadgets.php (added) (history)
  • /branches/Gadgets3.0/backend (added) (history)
  • /branches/Gadgets3.0/backend/Gadgets_body.php (added) (history)
  • /branches/Gadgets3.0/ui (added) (history)
  • /branches/Gadgets3.0/ui/SpecialGadgets.php (added) (history)

Diff [purge]

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' => '&#160;',
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' => '&#160;',
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 = "&#160; &#160; [$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 = '&#160;&#160;' . 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 @@
4040 $wgExtensionMessagesFiles['Gadgets'] = $dir . 'Gadgets.i18n.php';
4141 $wgExtensionAliasesFiles['Gadgets'] = $dir . 'Gadgets.alias.php';
4242
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';
4949
5050 $wgSpecialPages['Gadgets'] = 'SpecialGadgets';
5151 $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' => '&#160;',
 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' => '&#160;',
 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
1569 + LastChangedDate LastChangedRevision
Added: svn:mergeinfo
2570 Merged /branches/Gadgets-work/Gadgets_body.php:r73145-76526
3571 Merged /branches/wmf/1.17wmf1/extensions/Gadgets/Gadgets_body.php:r81884
Added: svn:eol-style
4572 + 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
1210 + Id
Added: svn:eol-style
2211 + 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
1124 + Id
Added: svn:eol-style
2125 + 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 = "&#160; &#160; [$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 = '&#160;&#160;' . 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
1169 + native

Status & tagging log