r24481 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r24480‎ | r24481 | r24482 >
Date:10:21, 31 July 2007
Author:daniel
Status:old
Tags:
Comment:
Gadgets extension: enable JS based gadgets via user preferences
Modified paths:
  • /trunk/extensions/Gadgets (added) (history)
  • /trunk/extensions/Gadgets/Gadgets.i18n.de.php (added) (history)
  • /trunk/extensions/Gadgets/Gadgets.i18n.php (added) (history)
  • /trunk/extensions/Gadgets/Gadgets.php (added) (history)
  • /trunk/extensions/Gadgets/README (added) (history)
  • /trunk/extensions/Gadgets/SpecialGadgets.php (added) (history)
  • /trunk/extensions/Gadgets/install.settings (added) (history)

Diff [purge]

Index: trunk/extensions/Gadgets/Gadgets.i18n.php
@@ -0,0 +1,29 @@
 2+<?php
 3+
 4+/**
 5+ * Internationalisation file for the ContactPage extension
 6+ *
 7+ * @package MediaWiki
 8+ * @subpackage Extensions
 9+ * @author Daniel Kinzler, brightbyte.de
 10+ * @copyright © 2007 Daniel Kinzler
 11+ * @licence GNU General Public Licence 2.0 or later
 12+ */
 13+
 14+#for Special:Preferences
 15+$messages['gadgetprefs']= 'Gadgets';
 16+$messages['gadgetprefstext']= 'Below is a list of special gadgets you can enable for your account.
 17+These gadgets are mostly based on JavaScript, so JavaScript has to be enabled in your browser for them to work.
 18+Note that these gadgets will have no effect on this preferences page.
 19+
 20+Also note that these special gadgets are not part of the MediaWiki software, and are usually developed and maintained
 21+by users on your local wiki. Local administrators can edit available gadgets using [[MediaWiki:Gadgets]]
 22+and [[Special:Gadgets]].';
 23+
 24+#for Special:Gadgets
 25+$messages['gadgets'] = 'Gadgets';
 26+$messages['gadgets-title'] = 'Gadgets';
 27+$messages['gadgets-pagetext'] = 'Below is a list of special gadgets users can enable on their preferences page, as defined by [[MediaWiki:Gadgets]].
 28+This overview provides easy access to the system message pages that define each gadget\'s description and code.';
 29+$messages['gadgets-uses'] = 'Uses';
 30+?>
Property changes on: trunk/extensions/Gadgets/Gadgets.i18n.php
___________________________________________________________________
Added: svn:eol-style
131 + native
Index: trunk/extensions/Gadgets/Gadgets.php
@@ -0,0 +1,216 @@
 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+ * @package MediaWiki
 10+ * @subpackage Extensions
 11+ * @author Daniel Kinzler, brightbyte.de
 12+ * @copyright © 2007 Daniel Kinzler
 13+ * @licence GNU General Public Licence 2.0 or later
 14+ */
 15+
 16+if( !defined( 'MEDIAWIKI' ) ) {
 17+ echo( "This file is an extension to the MediaWiki software and cannot be used standalone.\n" );
 18+ die( 1 );
 19+}
 20+
 21+$wgExtensionCredits['other'][] = array(
 22+ 'name' => 'Gadgets',
 23+ 'author' => 'Daniel Kinzler',
 24+ 'url' => 'http://mediawiki.org/wiki/Extension:Gadgets',
 25+ 'description' => 'lets users select custom javascript gadgets',
 26+);
 27+
 28+$wgHooks['InitPreferencesForm'][] = 'wfGadgetsInitPreferencesForm';
 29+$wgHooks['RenderPreferencesForm'][] = 'wfGadgetsRenderPreferencesForm';
 30+$wgHooks['ResetPreferences'][] = 'wfGadgetsResetPreferences';
 31+$wgHooks['BeforePageDisplay'][] = 'wfGadgetsBeforePageDisplay';
 32+
 33+$wgAutoloadClasses['SpecialGadgets'] = dirname( __FILE__ ) . '/SpecialGadgets.php';
 34+$wgSpecialPages['Gadgets'] = 'SpecialGadgets';
 35+
 36+function wfLoadGadgets() {
 37+ static $gadgets = NULL;
 38+
 39+ if ( $gadgets !== NULL ) return $gadgets;
 40+
 41+ $struct = wfLoadGadgetsStructured();
 42+ if ( !$struct ) {
 43+ $gadgets = $struct;
 44+ return $gadgets;
 45+ }
 46+
 47+ $gadgets = array();
 48+ foreach ( $struct as $section => $entries ) {
 49+ $gadgets = array_merge( $gadgets, $entries );
 50+ }
 51+
 52+ return $gadgets;
 53+}
 54+
 55+function wfLoadGadgetsStructured() {
 56+ static $gadgets = NULL;
 57+
 58+ if ( $gadgets !== NULL ) return $gadgets;
 59+
 60+ $g = wfMsgForContentNoTrans( "Gadgets" );
 61+ if ( wfEmptyMsg( "Gadgets", $g ) ) {
 62+ $gadgets = false;
 63+ return $gadgets;
 64+ }
 65+
 66+ $g = preg_replace( '/<!--.*-->/s', '', $g );
 67+ $g = preg_split( '/(\r\n|\r|\n)+/', $g );
 68+
 69+ $gadgets = array();
 70+ $section = '';
 71+
 72+ foreach ( $g as $line ) {
 73+ if ( preg_match( '/^==+ *([^*:\s|]+?)\s*==+\s*$/', $line, $m ) ) {
 74+ $section = $m[1];
 75+ }
 76+ else if ( preg_match( '/^\*+ *(\w[-\w\d]*)((\|[^|]*)+)\s*$/', $line, $m ) ) {
 77+ $name = $m[1];
 78+ $code = preg_split( '/\s*\|\s*/', $m[2], -1, PREG_SPLIT_NO_EMPTY );
 79+
 80+ if ( $code ) {
 81+ $gadgets[$section][$name] = $code;
 82+ }
 83+ }
 84+ }
 85+
 86+ return $gadgets;
 87+}
 88+
 89+function wfGadgetsInitPreferencesForm( &$prefs, &$request ) {
 90+ $gadgets = wfLoadGadgets();
 91+ if ( !$gadgets ) return true;
 92+
 93+ foreach ( $gadgets as $gname => $code ) {
 94+ $tname = "gadget-$gname";
 95+ $prefs->mToggles[ $tname ] = $request->getCheck( "wpOp$tname" ) ? 1 : 0;
 96+ }
 97+
 98+ return true;
 99+}
 100+
 101+function wfGadgetsResetPreferences( &$prefs, &$user ) {
 102+ $gadgets = wfLoadGadgets();
 103+ if ( !$gadgets ) return true;
 104+
 105+ foreach ( $gadgets as $gname => $code ) {
 106+ $tname = "gadget-$gname";
 107+ $prefs->mToggles[ $tname ] = $user->getOption( $tname );
 108+ }
 109+
 110+ return true;
 111+}
 112+
 113+function wfGadgetsRenderPreferencesForm( &$prefs, &$out ) {
 114+ $gadgets = wfLoadGadgetsStructured();
 115+ if ( !$gadgets ) return true;
 116+
 117+ loadGadgetsI18n();
 118+
 119+ $out->addHtml( "\n<fieldset>\n<legend>" . wfMsgHtml( 'gadgetprefs' ) . "</legend>\n" );
 120+
 121+ $out->addHtml( "<p>" . wfMsgWikiHtml( 'gadgetprefstext' ) . "</p>\n" );
 122+ #$out->addHtml( "<p>" . wfMsgWikiHtml( 'gadgetreloadhint' ) . "</p>\n" );
 123+
 124+ $msgOpt = array( 'parseinline', 'parsemag' );
 125+
 126+ foreach ( $gadgets as $section => $entries ) {
 127+ if ( $section !== false && $section !== '' ) {
 128+ $ttext = wfMsgExt( $section, $msgOpt );
 129+ $out->addHtml( "\n<h2>" . $ttext . "</h2>\n" );
 130+ }
 131+
 132+ foreach ( $entries as $gname => $code ) {
 133+ $tname = "gadget-$gname";
 134+ $ttext = wfMsgExt( $gname, $msgOpt );
 135+ $checked = @$prefs->mToggles[ $tname ] == 1 ? ' checked="checked"' : '';
 136+ $disabled = '';
 137+
 138+ $out->addHtml( "<div class='toggle'><input type='checkbox' value='1' id=\"$tname\" name=\"wpOp$tname\"$checked$disabled />" .
 139+ " <span class='toggletext'><label for=\"$tname\">$ttext</label></span></div>\n" );
 140+ }
 141+ }
 142+
 143+ #$out->addHtml( "<p>" . wfMsgWikiHtml( 'gadgetreloadhint' ) . "</p>\n" );
 144+ $out->addHtml( "</fieldset>\n\n" );
 145+
 146+ return true;
 147+}
 148+
 149+function wfGadgetsBeforePageDisplay( &$out ) {
 150+ global $wgUser, $wgTitle;
 151+ if ( !$wgUser->isLoggedIn() ) return true;
 152+
 153+ //disable all gadgets on Special:Preferences
 154+ if ( $wgTitle->getNamespace() == NS_SPECIAL ) {
 155+ $name = SpecialPage::resolveAlias( $wgTitle->getText() );
 156+ if ( $name == "Preferences" ) return true;
 157+ }
 158+
 159+ $gadgets = wfLoadGadgets();
 160+ if ( !$gadgets ) return true;
 161+
 162+ $done = array();
 163+
 164+ foreach ( $gadgets as $gname => $code ) {
 165+ $tname = "gadget-$gname";
 166+ if ( $wgUser->getOption( $tname ) ) {
 167+ wfApplyGadgetCode( $code, $out, $done );
 168+ }
 169+ }
 170+
 171+ return true;
 172+}
 173+
 174+function wfApplyGadgetCode( $code, &$out, &$done ) {
 175+ global $wgSkin, $wgJsMimeType;
 176+
 177+ //FIXME: stuff added via $out->addScript appears below usercss and userjs in the head tag.
 178+ // but we'd want it to appear above explicite user stuff, so it can be overwritten.
 179+ foreach ( $code as $codePage ) {
 180+ //include only once
 181+ if ( isset( $done[ $codePage ] ) ) continue;
 182+ $done[ $codePage ] = true;
 183+
 184+ $t = Title::makeTitleSafe( NS_MEDIAWIKI, $codePage );
 185+ if ( !$t ) continue;
 186+
 187+ if ( preg_match( '/\.js/', $codePage ) ) {
 188+ $u = $t->getFullURL( 'action=raw&ctype=' . $wgJsMimeType );
 189+ $out->addScript( '<script type="' . $wgJsMimeType . '" src="' . htmlspecialchars( $u ) . '"></script>' . "\n" );
 190+ }
 191+ else if ( preg_match( '/\.css/', $codePage ) ) {
 192+ $u = $t->getFullURL( 'action=raw&ctype=text/css' );
 193+ $out->addScript( '<style type="text/css">/*<![CDATA[*/ @import "' . $u . '"; /*]]>*/</style>' . "\n" );
 194+ }
 195+ }
 196+}
 197+
 198+function loadGadgetsI18n() {
 199+ global $wgLang, $wgMessageCache;
 200+
 201+ static $initialized = false;
 202+
 203+ if ( $initialized ) return;
 204+
 205+ $messages= array();
 206+
 207+ $f= dirname( __FILE__ ) . '/Gadgets.i18n.php';
 208+ include( $f );
 209+
 210+ $f= dirname( __FILE__ ) . '/Gadgets.i18n.' . $wgLang->getCode() . '.php';
 211+ if ( file_exists( $f ) ) include( $f );
 212+
 213+ $initialized = true;
 214+ $wgMessageCache->addMessages( $messages );
 215+}
 216+
 217+?>
\ No newline at end of file
Property changes on: trunk/extensions/Gadgets/Gadgets.php
___________________________________________________________________
Added: svn:eol-style
1218 + native
Index: trunk/extensions/Gadgets/SpecialGadgets.php
@@ -0,0 +1,90 @@
 2+<?php
 3+/**
 4+ * Speclial:Gadgets, provides a preview of MediaWiki:Gadgets.
 5+ *
 6+ * @addtogroup SpecialPage
 7+ * @author Daniel Kinzler, brightbyte.de
 8+ * @copyright © 2007 Daniel Kinzler
 9+ * @licence GNU General Public Licence 2.0 or later
 10+ */
 11+
 12+if( !defined( 'MEDIAWIKI' ) ) {
 13+ echo( "not a valid entry point.\n" );
 14+ die( 1 );
 15+}
 16+
 17+/**
 18+ *
 19+ */
 20+class SpecialGadgets extends SpecialPage {
 21+
 22+ /**
 23+ * Constructor
 24+ */
 25+ function __construct() {
 26+ global $wgOut;
 27+ SpecialPage::SpecialPage( 'Gadgets', '', true );
 28+
 29+ #inject messages
 30+ loadGadgetsI18n();
 31+ }
 32+
 33+ /**
 34+ * Main execution function
 35+ * @param $par Parameters passed to the page
 36+ */
 37+ function execute( $par ) {
 38+ global $wgOut, $wgUser;
 39+ $skin =& $wgUser->getSkin();
 40+
 41+ $wgOut->setPagetitle( wfMsg( "gadgets-title" ) );
 42+ $wgOut->addWikiText( wfMsg( "gadgets-pagetext" ) );
 43+
 44+ $gadgets = wfLoadGadgetsStructured();
 45+ if ( !$gadgets ) return;
 46+
 47+ $wgOut->addHTML( '<ul>' );
 48+
 49+ $msgOpt = array( 'parseinline', 'parsemag' );
 50+
 51+ foreach ( $gadgets as $section => $entries ) {
 52+ if ( $section !== false && $section !== '' ) {
 53+ $t = Title::makeTitleSafe( NS_MEDIAWIKI, $section );
 54+ $lnk = $t ? $skin->makeLinkObj( $t, wfMsgHTML("edit") ) : htmlspecialchars($section);
 55+ $ttext = wfMsgExt( $section, $msgOpt );
 56+
 57+ $wgOut->addHTML( "\n<h2>$ttext &nbsp; &nbsp; [$lnk]</h2>\n" );
 58+ }
 59+
 60+ foreach ( $entries as $gname => $code ) {
 61+ $t = Title::makeTitleSafe( NS_MEDIAWIKI, $gname );
 62+ if ( !$t ) continue;
 63+
 64+ $lnk = $skin->makeLinkObj( $t, wfMsgHTML("edit") );
 65+ $ttext = wfMsgExt( $gname, $msgOpt );
 66+
 67+ $wgOut->addHTML( "<li>" );
 68+ $wgOut->addHTML( "$ttext &nbsp; &nbsp; [$lnk]<br/>" );
 69+
 70+ $wgOut->addHTML( wfMsgHTML("gadgets-uses") . ": " );
 71+
 72+ $first = true;
 73+ foreach ( $code as $codePage ) {
 74+ $t = Title::makeTitleSafe( NS_MEDIAWIKI, $codePage );
 75+ if ( !$t ) continue;
 76+
 77+ if ( $first ) $first = false;
 78+ else $wgOut->addHTML(", ");
 79+
 80+ $lnk = $skin->makeLinkObj( $t, htmlspecialchars( $t->getText() ) );
 81+ $wgOut->addHTML($lnk);
 82+ }
 83+
 84+ $wgOut->addHtml( "</li>" );
 85+ }
 86+ }
 87+
 88+ $wgOut->addHTML( '</ul>' );
 89+ }
 90+}
 91+?>
Property changes on: trunk/extensions/Gadgets/SpecialGadgets.php
___________________________________________________________________
Added: svn:eol-style
192 + native
Index: trunk/extensions/Gadgets/install.settings
@@ -0,0 +1,2 @@
 2+require_once( "{{path}}/Gadgets.php" );
 3+
Index: trunk/extensions/Gadgets/Gadgets.i18n.de.php
@@ -0,0 +1,30 @@
 2+<?php
 3+
 4+/**
 5+ * German iternationalisation file for the ContactPage extension
 6+ *
 7+ * @package MediaWiki
 8+ * @subpackage Extensions
 9+ * @author Daniel Kinzler, brightbyte.de
 10+ * @copyright © 2007 Daniel Kinzler
 11+ * @licence GNU General Public Licence 2.0 or later
 12+ */
 13+
 14+#for Special:Preferences
 15+$messages['gadgetprefs']= 'Gadgets';
 16+$messages['gadgetprefstext']= 'Liste von speziellen Gadgets die für jeden Benutzer aktiviert werden können.
 17+Die Gadgets basieren zumeinst auf JavaScript, daher muss JavaScript im Browser aktiviert sein, damit sie funktionieren.
 18+Die Gadgets funktionieren allerdings nicht auf dieser Seite mit persönlichen Einstellungen.
 19+
 20+Ausserdem ist zu beachten, dass diese Gadgets im Allgemeinen nicht Teil von MediaWiki sind, sondern meist von
 21+Benutzern des lokalen Wikis entwickelt und gewartet werden. Lokale Wiki-Administratoren können die Liste von
 22+verfügbaren Gadgets auf der Seite [[MediaWiki:Gadgets]] bearbeiten';
 23+
 24+#for Special:Gadgets
 25+$messages['gadgets'] = 'Gadgets';
 26+$messages['gadgets-title'] = 'Gadgets';
 27+$messages['gadgets-pagetext'] = 'Liste von speziellen Gadgets, die für jeden Benutzer verfügbar sind, wie in [[MediaWiki:Gadgets]] definiert.
 28+Diese Übersicht bietet direkten Zugang zu den Systemnachrichten, die die Beschreibung sowie den Programmcode jedes
 29+Gadgets enthalten.';
 30+$messages['gadgets-uses'] = 'Benutzt';
 31+?>
Property changes on: trunk/extensions/Gadgets/Gadgets.i18n.de.php
___________________________________________________________________
Added: svn:eol-style
132 + native
Index: trunk/extensions/Gadgets/README
@@ -0,0 +1,77 @@
 2+--------------------------------------------------------------------------
 3+README for the Gadgets extension
 4+Copyright © 2007 Daniel Kinzler
 5+Licenses: GNU General Public Licence (GPL)
 6+ GNU Free Documentation License (GFDL)
 7+--------------------------------------------------------------------------
 8+
 9+The Gadgets extension provides a way for users to pick JavaScript or CSS
 10+based "gadgets" that other wiki users provide.
 11+
 12+<http://mediawiki.org/wiki/Extension:Gadgets>
 13+
 14+The Gadgets extension was originally written by Daniel Kinzler in 2007
 15+and is released under the GNU General Public Licence (GPL).
 16+The internationalization files may contain contributions by several people;
 17+they should be mentioned in each file individually.
 18+
 19+== Installing ==
 20+Copy the Gadgets directory into the extensions folder of your
 21+MediaWiki installation. Then add the following lines to your
 22+LocalSettings.php file (near the end):
 23+
 24+ require_once( "$IP/extensions/Gadgets/Gadgets.php" );
 25+
 26+== Usage ==
 27+The list of available gadgets is defined on MediaWiki:Gadgets. Gadgets
 28+defined there show up in the "Gadgets" section of Special:Preferences, so
 29+users can pick the gadgets they would like to use. An overview of the
 30+gadgets defined by MediaWiki:Gadgets is also shown on Special:Gadgets,
 31+along with links to the respective system messages, for easy editing.
 32+
 33+Each line in MediaWiki:Gadgets that start with one or more "*" (asterisc)
 34+characters defines a gadget; it must have the following form:
 35+
 36+ * mygadget|mygadget.js|mygadget.css
 37+
 38+That is, each line consists of fields separated by a "|" (pipe) character.
 39+The first field ("mygadget" in the example) is the gadgets internal name,
 40+and references a system message (MediaWiki:Mygadget in the example)
 41+that contains a short descriptiopn of the gadget, using wiki syntax.
 42+Note that the internal name must start with a ASCII letter, and must
 43+contain only ASCII letter and numbers.
 44+
 45+The remaining fields on the line refer to the JavaScript or CSS code that
 46+makes up the gadget, contained in system messages (MediaWiki:Mygadget.js
 47+and MediaWiki:Mygadget.css in the example); the names of those messages
 48+must end with ".js" or ".css", respectively. A gadget can use any number
 49+of code messages, specifically, common code can be put into a code message
 50+used by several gadgets, in addition to their own specific code, e.g:
 51+
 52+ * frobinator|commonStuff.js|frob.js|frob.css|pretty.css
 53+ * l33t|commonStuff.js|tools.js|l33t.js
 54+
 55+The list of gadgets in MediaWiki:Gadgets can be broken into sections using
 56+lines that start and end with two or more "=" (equals) characters, enclosing
 57+the name of a system message that defines the section's name - for example:
 58+
 59+ == editing-gadgets ==
 60+
 61+This would define a new section, with the title defined on the page
 62+MediaWiki:Editing-gadgets
 63+
 64+
 65+== Caveats ==
 66+
 67+* Requires MediaWiki 1.11alpha, revision 24477 or later.
 68+* Gadgets do not apply to Special:Preferences, so users can always disable
 69+ any broken gadgets they may have enabled.
 70+* Uses BeforePageDisplay hook, thus only works with MonoBook based skins;
 71+ specifically, does not work with CologneBlue.
 72+* Gadget code is included after user code - that means that user JS has no
 73+ access to things defined in gadgets, and user CSS is overwritten by CSS
 74+ from gadgets. (pending a better way to insert things into the HTML head)
 75+* MediaWiki:Gadgets is parsed for every page request by a logged in user.
 76+ It would be nice to make the MessageCache more flexible, so it can store
 77+ a parsed version of the MediaWiki:Gadgets.
 78+

Status & tagging log