http://www.mediawiki.org/wiki/Special:Code/MediaWiki/92340
Revision: 92340 Author: salvatoreingala Date: 2011-07-15 23:18:03 +0000 (Fri, 15 Jul 2011) Log Message: ----------- - Added timestamp to saved preferences, so that gadget preferences module may compute getModifiedTime() meaningfully - Splitted gadget options from gadget module: Gadget's module is now 'ext.Gadget.foo' => GadgetResourceLoaderModule while gadget preferences are in 'ext.Gadget.foo.prefs' => GadgetOptionsResourceLoaderModule; the latter is in the 'private' group - Now it loads default preferences for anonymous users. - Moved GadgetsMainModule.php to the /backend folder Modified Paths: -------------- branches/salvatoreingala/Gadgets/Gadgets.php branches/salvatoreingala/Gadgets/Gadgets_tests.php branches/salvatoreingala/Gadgets/backend/Gadget.php branches/salvatoreingala/Gadgets/backend/GadgetHooks.php branches/salvatoreingala/Gadgets/backend/GadgetPrefs.php branches/salvatoreingala/Gadgets/backend/GadgetResourceLoaderModule.php Added Paths: ----------- branches/salvatoreingala/Gadgets/backend/GadgetOptionsResourceLoaderModule.php branches/salvatoreingala/Gadgets/backend/GadgetsMainModule.php Removed Paths: ------------- branches/salvatoreingala/Gadgets/ui/GadgetsMainModule.php Modified: branches/salvatoreingala/Gadgets/Gadgets.php =================================================================== --- branches/salvatoreingala/Gadgets/Gadgets.php 2011-07-15 23:08:02 UTC (rev 92339) +++ branches/salvatoreingala/Gadgets/Gadgets.php 2011-07-15 23:18:03 UTC (rev 92340) @@ -48,8 +48,9 @@ $wgAutoloadClasses['Gadget'] = $dir . 'backend/Gadget.php'; $wgAutoloadClasses['GadgetHooks'] = $dir . 'backend/GadgetHooks.php'; $wgAutoloadClasses['GadgetResourceLoaderModule'] = $dir . 'backend/GadgetResourceLoaderModule.php'; +$wgAutoloadClasses['GadgetOptionsResourceLoaderModule'] = $dir . 'backend/GadgetOptionsResourceLoaderModule.php'; $wgAutoloadClasses['GadgetPrefs'] = $dir . 'backend/GadgetPrefs.php'; -$wgAutoloadClasses['GadgetsMainModule'] = $dir . 'ui/GadgetsMainModule.php'; +$wgAutoloadClasses['GadgetsMainModule'] = $dir . 'backend/GadgetsMainModule.php'; $wgAutoloadClasses['SpecialGadgets'] = $dir . 'ui/SpecialGadgets.php'; $wgSpecialPages['Gadgets'] = 'SpecialGadgets'; @@ -62,7 +63,7 @@ $wgAjaxExportList[] = 'GadgetsAjax::setPreferences'; $wgResourceModules['ext.gadgets'] = array( - 'class' => 'GadgetsMainModule' + 'class' => 'GadgetsMainModule', ); $wgResourceModules['jquery.validate'] = array( Modified: branches/salvatoreingala/Gadgets/Gadgets_tests.php =================================================================== --- branches/salvatoreingala/Gadgets/Gadgets_tests.php 2011-07-15 23:08:02 UTC (rev 92339) +++ branches/salvatoreingala/Gadgets/Gadgets_tests.php 2011-07-15 23:18:03 UTC (rev 92340) @@ -589,8 +589,24 @@ ) ) ); } - + /** + * Tests Gadget::getDefaults + * + * @dataProvider prefsDescProvider + */ + function testGetDefaults( $prefsDescription ) { + $this->assertEquals( GadgetPrefs::getDefaults( $prefsDescription ), array( + 'testBoolean' => true, + 'testBoolean2' => true, + 'testNumber' => 7, + 'testNumber2' => 7, + 'testSelect' => 3, + 'testSelect2' => 3 + ) ); + } + + /** * Tests Gadget::setPrefsDescription, GadgetPrefs::checkPrefsAgainstDescription, * GadgetPrefs::matchPrefsWithDescription and Gadget::setPrefs. * Modified: branches/salvatoreingala/Gadgets/backend/Gadget.php =================================================================== --- branches/salvatoreingala/Gadgets/backend/Gadget.php 2011-07-15 23:08:02 UTC (rev 92339) +++ branches/salvatoreingala/Gadgets/backend/Gadget.php 2011-07-15 23:18:03 UTC (rev 92340) @@ -22,6 +22,7 @@ */ const GADGET_CLASS_VERSION = 5; + //Fields stored in cache private $version = self::GADGET_CLASS_VERSION, $scripts = array(), $styles = array(), @@ -32,9 +33,10 @@ $requiredRights = array(), $onByDefault = false, $category, - $mTime = null, //upper bound on last modification time; UNIX timestamp $prefsDescription = null, - $preferences = null; + //The following fields are initialized after saving the gadget to cache for registered users + $preferences = null, + $prefsTimestamp = 1; //last time user preferences for this gadget have been changed; UNIX timestamp /** * Creates an instance of this class from definition in MediaWiki:Gadgets-definition @@ -55,9 +57,6 @@ $gadget = new Gadget(); $gadget->name = trim( str_replace(' ', '_', $m[1] ) ); $gadget->definition = $definition; - - //TODO: make this more precise with gadget-specific info. Untile then, 'now' is an upper bound. - $gadget->mTime = wfTimestamp( TS_UNIX ); //Parse gadget options $options = trim( $m[2], ' []' ); @@ -114,6 +113,9 @@ if ( isset( $prefsDescriptionJson ) ) { $prefsDescription = FormatJson::decode( $prefsDescriptionJson, true ); $gadget->setPrefsDescription( $prefsDescription ); + + //Load default gadget preferences. Only useful for anonymous users + $gadget->setPrefs( GadgetPrefs::getDefaults( $prefsDescription ) ); } } @@ -156,6 +158,13 @@ } /** + * @return String: Name of ResourceLoader module for this gadget's preferences + */ + public function getPrefsModuleName() { + return "{$this->getModuleName()}.prefs"; + } + + /** * Checks whether this is an instance of an older version of this class deserialized from cache * @return Boolean */ @@ -255,14 +264,15 @@ return new GadgetResourceLoaderModule( $pages, $this->dependencies, $this ); } + /** - * Returns an upper bound on the modification time of the gadget. - * Used by GadgetResourceLoaderModule to compute its own mTime. + * Returns ResourceLoader module for this gadget's preferences, see + * getPrefsModuleName(). * - * @return String the UNIX timestamp of this gadget's modificaton time. + * @return Mixed: GadgetOptionsResourceLoaderModule or false */ - public function getModifiedTime() { - return $this->mTime; + public function getPrefsModule() { + return new GadgetOptionsResourceLoaderModule( $this ); } /** @@ -492,9 +502,30 @@ $this->preferences = $prefs; if ( $savePrefs ) { + $this->setPrefsTimestamp( wfTimestamp( TS_UNIX ) ); //update timestamp before saving $user = RequestContext::getMain()->getUser(); $user->saveSettings(); } return true; } + + /** + * Returns the modification time of gadget preferences. + * Used by GadgetResourceLoaderModule to compute its own mTime. + * Returns 1 if setPrefsTimestamp() has never been called, or the previously stored value otherwise. + * + * @return String the UNIX timestamp of this gadget's modificaton time. + */ + public function getPrefsTimestamp() { + return $this->prefsTimestamp; + } + + /** + * Sets the modification time of gadget preferences. + * + * @param $timestamp String: the UNIX timestamp of the last time preferences has been saved. + */ + public function setPrefsTimestamp( $timestamp ) { + $this->prefsTimestamp = $timestamp; + } } Modified: branches/salvatoreingala/Gadgets/backend/GadgetHooks.php =================================================================== --- branches/salvatoreingala/Gadgets/backend/GadgetHooks.php 2011-07-15 23:08:02 UTC (rev 92339) +++ branches/salvatoreingala/Gadgets/backend/GadgetHooks.php 2011-07-15 23:18:03 UTC (rev 92340) @@ -148,6 +148,9 @@ foreach ( $gadgets as $g ) { $module = $g->getModule(); if ( $module ) { + if ( $g->getPrefsDescription() !== null ) { + $resourceLoader->register( $g->getPrefsModuleName(), $g->getPrefsModule() ); + } $resourceLoader->register( $g->getModuleName(), $module ); } } @@ -230,13 +233,15 @@ //Find out all existing gadget preferences and save them in a map $preferencesCache = array(); + $timestampCache = array(); foreach ( $options as $option => $value ) { $m = array(); if ( preg_match( '/gadget-([a-zA-Z](?:[-_:.\w\d ]*[a-zA-Z0-9])?)-config/', $option, $m ) ) { $gadgetName = trim( str_replace(' ', '_', $m[1] ) ); - $gadgetPrefs = unserialize( $value ); - if ( $gadgetPrefs !== false ) { - $preferencesCache[$gadgetName] = $gadgetPrefs; + $bundle = unserialize( $value ); + if ( is_array( $bundle ) && isset( $bundle['timestamp'] ) && isset( $bundle['prefs'] ) ) { + $preferencesCache[$gadgetName] = $bundle['prefs']; + $timestampCache[$gadgetName] = $bundle['timestamp']; } else { //should not happen; just in case wfDebug( __METHOD__ . ": couldn't unserialize settings for gadget " . @@ -252,15 +257,18 @@ if ( $prefsDescription !== null ) { if ( isset( $preferencesCache[$gadget->getName()] ) ) { $userPrefs = $preferencesCache[$gadget->getName()]; + $timestamp = $timestampCache[$gadget->getName()]; } if ( !isset( $userPrefs ) ) { $userPrefs = array(); //no saved prefs (or invalid entry in DB), use defaults + $timestamp = 1; } - + GadgetPrefs::matchPrefsWithDescription( $prefsDescription, $userPrefs ); $gadget->setPrefs( $userPrefs ); + $gadget->setPrefsTimestamp( $timestamp ); } } @@ -296,16 +304,19 @@ $prefsDescription = $gadget->getPrefsDescription(); //Remove preferences that equal their default - foreach ( $prefs as $prefName => $value ) { - if ( $prefsDescription['fields'][$prefName]['default'] === $value ) { + foreach ( $prefsDescription['fields'] as $prefDescription ) { + $prefName = $prefDescription['name']; + $prefDefault = $prefDescription['default']; + if ( $prefs[$prefName] === $prefDefault ) { unset( $prefs[$prefName] ); } } - //Only save it if at least one preference differs from default - if ( !empty( $prefs ) ) { - $options["gadget-{$gadget->getName()}-config"] = serialize( $prefs ); - } + //Save back preferences + $options["gadget-{$gadget->getName()}-config"] = serialize( array( + 'timestamp' => $gadget->getPrefsTimestamp(), + 'prefs' => $prefs + ) ); } } Added: branches/salvatoreingala/Gadgets/backend/GadgetOptionsResourceLoaderModule.php =================================================================== --- branches/salvatoreingala/Gadgets/backend/GadgetOptionsResourceLoaderModule.php (rev 0) +++ branches/salvatoreingala/Gadgets/backend/GadgetOptionsResourceLoaderModule.php 2011-07-15 23:18:03 UTC (rev 92340) @@ -0,0 +1,75 @@ +<?php + +/** + * Gadgets extension - lets users select custom javascript gadgets + * + * + * For more info see http://mediawiki.org/wiki/Extension:Gadgets + * + * @file + * @ingroup Extensions + * @author Daniel Kinzler, brightbyte.de + * @copyright © 2007 Daniel Kinzler + * @license GNU General Public Licence 2.0 or later + */ + +/** + * Class representing the user-specific options for a gadget + */ +class GadgetOptionsResourceLoaderModule extends ResourceLoaderModule { + private $gadget; + + /** + * Creates an instance of this class + * @param $gadget Gadget: the gadget this module is built upon. + */ + public function __construct( $gadget ) { + $this->gadget = $gadget; + } + + /** + * Overrides ResourceLoaderModule::getDependencies() + * @return Array: Names of resources this module depends on + */ + public function getDependencies() { + return array( 'ext.gadgets' ); + } + + /** + * Overrides ResourceLoaderModule::getGroup() + * @return String + */ + public function getGroup() { + return 'private'; + } + + /** + * Overrides ResourceLoaderModule::getScript() + * @param $context ResourceLoaderContext + * @return String + */ + public function getScript( ResourceLoaderContext $context ) { + $gadgetInfo = array( + 'name' => $this->gadget->getName(), + 'config' => $this->gadget->getPrefs() + ); + return Xml::encodeJsCall( 'mw.gadgets.info.set', + array( $this->gadget->getName(), $gadgetInfo ) ); + } + + /** + * Overrides ResourceLoaderModule::getModifiedTime() + * @param $context ResourceLoaderContext + * @return Integer + */ + public function getModifiedTime( ResourceLoaderContext $context ) { + $prefsMTime = $this->gadget->getPrefsTimestamp(); + + $resourceLoader = $context->getResourceLoader(); + $parentModule = $resourceLoader->getModule( $this->gadget->getModuleName() ); + $gadgetMTime = $parentModule->getModifiedTime( $context ); + + return max( $gadgetMTime, $prefsMTime ); + } +} + Property changes on: branches/salvatoreingala/Gadgets/backend/GadgetOptionsResourceLoaderModule.php ___________________________________________________________________ Added: svn:eol-style + native Modified: branches/salvatoreingala/Gadgets/backend/GadgetPrefs.php =================================================================== --- branches/salvatoreingala/Gadgets/backend/GadgetPrefs.php 2011-07-15 23:08:02 UTC (rev 92339) +++ branches/salvatoreingala/Gadgets/backend/GadgetPrefs.php 2011-07-15 23:18:03 UTC (rev 92340) @@ -534,6 +534,20 @@ } /** + * Return default preferences according to the given description. + * + * @param $prefsDescription Array: reference of the array of preferences to match. + * It is assumed that $prefsDescription is a valid description of preferences. + * + * @return Array: the set of default preferences, keyed by preference name. + */ + public static function getDefaults( $prefsDescription ) { + $prefs = array(); + self::matchPrefsWithDescription( $prefsDescription, $prefs ); + return $prefs; + } + + /** * Returns true if $str should be interpreted as a message, false otherwise. * * @param $str String Modified: branches/salvatoreingala/Gadgets/backend/GadgetResourceLoaderModule.php =================================================================== --- branches/salvatoreingala/Gadgets/backend/GadgetResourceLoaderModule.php 2011-07-15 23:08:02 UTC (rev 92339) +++ branches/salvatoreingala/Gadgets/backend/GadgetResourceLoaderModule.php 2011-07-15 23:18:03 UTC (rev 92340) @@ -28,6 +28,7 @@ * 'MediaWiki:Gadget-foo.css' => array( 'type' => 'style' ), * ) * @param $dependencies Array: Names of resources this module depends on + * @param $gadget Gadget: the gadget this module is built upon. */ public function __construct( $pages, $dependencies, $gadget ) { $this->pages = $pages; @@ -48,47 +49,48 @@ * @return Array: Names of resources this module depends on */ public function getDependencies() { - return $this->dependencies; - } - - public function getGroup() { - //Modules for gadgets with preferences must be kept private, if the user can set preferences - if ( $this->gadget->getPrefsDescription() !== null - && RequestContext::getMain()->getUser()->isLoggedIn() ) - { - return 'private'; - } else { - return parent::getGroup(); + $deps = array( 'ext.gadgets' ); + if ( $this->gadget->getPrefsDescription() !== null ){ + $deps[] = $this->gadget->getPrefsModuleName(); } + + return array_merge( + $this->dependencies, + $deps + ); } + /** + * Overrides ResourceLoaderModule::getScript() + * @param $context ResourceLoaderContext + * @return String + */ public function getScript( ResourceLoaderContext $context ) { $prefs = $this->gadget->getPrefs(); //Enclose gadget's code in a closure, with "this" bound to the //configuration object (or to "window" for non-configurable gadgets) - $header = '(function(){'; + $header = "(function(){"; - //TODO: it may be nice add other metadata for the gadget - $boundObject = array( 'config' => $prefs ); - - if ( $prefs !== NULL ) { - //Bind configuration object to "this". - $footer = '}).' . Xml::encodeJsCall( 'apply', - array( $boundObject, array() ) - ) . ';'; + if ( $prefs !== null ) { + //Bind gadget info to "this". + $footer = "}).apply( mw.gadgets.info.get('{$this->gadget->getName()}') );"; } else { //Bind window to "this" - $footer = '}).apply( window, [] );'; + $footer = "}).apply( window );"; } return $header . parent::getScript( $context ) . $footer; } + /** + * Overrides ResourceLoaderModule::getModifiedTime() + * @param $context ResourceLoaderContext + * @return Integer + */ public function getModifiedTime( ResourceLoaderContext $context ) { - $touched = wfTimestamp( TS_UNIX, RequestContext::getMain()->getUser()->getTouched() ); - $gadgetMTime = $this->gadget->getModifiedTime(); - return max( parent::getModifiedTime( $context ), $touched, $gadgetMTime ); + //TODO: should also depend on the mTime of preferences description page + return parent::getModifiedTime( $context ); } } Copied: branches/salvatoreingala/Gadgets/backend/GadgetsMainModule.php (from rev 91026, branches/salvatoreingala/Gadgets/ui/GadgetsMainModule.php) =================================================================== --- branches/salvatoreingala/Gadgets/backend/GadgetsMainModule.php (rev 0) +++ branches/salvatoreingala/Gadgets/backend/GadgetsMainModule.php 2011-07-15 23:18:03 UTC (rev 92340) @@ -0,0 +1,50 @@ +<?php + +/** + * Gadgets extension - lets users select custom javascript gadgets + * + * + * For more info see http://mediawiki.org/wiki/Extension:Gadgets + * + * @file + * @ingroup Extensions + * @author Daniel Kinzler, brightbyte.de + * @copyright © 2007 Daniel Kinzler + * @license GNU General Public Licence 2.0 or later + */ + +/** + * Class implementing the ext.gadgets module. Required by ext.gadgets.preferences. + */ +class GadgetsMainModule extends ResourceLoaderModule { + + public function getModifiedTime( ResourceLoaderContext $context ) { + $gadgets = Gadget::loadList(); + + $m = 1; + $resourceLoader = $context->getResourceLoader(); + foreach ( $gadgets as $gadget ) { + if ( $gadget->hasModule() ) { + $module = $resourceLoader->getModule( $gadget->getModuleName() ); + $m = max( $m, $module->getModifiedTime( $context ) ); + } + } + return $m; + } + + public function getScript( ResourceLoaderContext $context ) { + $configurableGadgets = array(); + $gadgets = Gadget::loadList(); + + foreach ( $gadgets as $gadget ) { + if ( $gadget->getPrefsDescription() !== null ) { + $configurableGadgets[] = $gadget->getName(); + } + } + + $script = "mw.gadgets = {};\n"; + $script .= "mw.gadgets.info = new mw.Map();\n"; + $script .= "mw.gadgets.configurableGadgets = " . Xml::encodeJsVar( $configurableGadgets ) . ";\n"; + return $script; + } +} Deleted: branches/salvatoreingala/Gadgets/ui/GadgetsMainModule.php =================================================================== --- branches/salvatoreingala/Gadgets/ui/GadgetsMainModule.php 2011-07-15 23:08:02 UTC (rev 92339) +++ branches/salvatoreingala/Gadgets/ui/GadgetsMainModule.php 2011-07-15 23:18:03 UTC (rev 92340) @@ -1,45 +0,0 @@ -<?php - -/** - * Gadgets extension - lets users select custom javascript gadgets - * - * - * For more info see http://mediawiki.org/wiki/Extension:Gadgets - * - * @file - * @ingroup Extensions - * @author Daniel Kinzler, brightbyte.de - * @copyright © 2007 Daniel Kinzler - * @license GNU General Public Licence 2.0 or later - */ - -/** - * Class implementing the ext.gadgets module. Required by ext.gadgets.preferences. - */ -class GadgetsMainModule extends ResourceLoaderModule { - - public function getModifiedTime( ResourceLoaderContext $context ) { - $gadgets = Gadget::loadList(); - - $m = 0; - foreach ( $gadgets as $gadget ) { - $m = max( $m, $gadget->getModifiedTime() ); - } - return $m; - } - - public function getScript( ResourceLoaderContext $context ) { - $configurableGadgets = array(); - $gadgets = Gadget::loadList(); - - foreach ( $gadgets as $gadget ) { - if ( $gadget->getPrefsDescription() !== null ) { - $configurableGadgets[] = $gadget->getName(); - } - } - - $script = "mw.gadgets = {}\n"; - $script .= "mw.gadgets.configurableGadgets = " . Xml::encodeJsVar( $configurableGadgets ) . ";\n"; - return $script; - } -} _______________________________________________ MediaWiki-CVS mailing list MediaWiki-CVS@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs