Index: branches/salvatoreingala/Gadgets/Gadgets_body.php |
— | — | @@ -166,42 +166,35 @@ |
167 | 167 | return true; |
168 | 168 | } |
169 | 169 | |
170 | | - //Remove gadget-*-config options, since they must not be delivered |
171 | | - //via mw.user.options like other user preferences |
172 | | - $gadgets = Gadget::loadList(); |
173 | | - |
174 | | - if ( !$gadgets ) { |
175 | | - return true; |
176 | | - } |
177 | | - |
178 | | - $existingPrefs = array(); |
| 170 | + //Find out all existing gadget preferences and save them in a map |
| 171 | + $preferencesCache = array(); |
179 | 172 | foreach ( $options as $option => $value ) { |
180 | 173 | $m = array(); |
181 | 174 | if ( preg_match( '/gadget-([a-zA-Z](?:[-_:.\w\d ]*[a-zA-Z0-9])?)-config/', $option, $m ) ) { |
182 | 175 | $gadgetName = $m[1]; |
183 | | - $existingPrefs[$gadgetName] = $value; |
| 176 | + $preferencesCache[$gadgetName] = FormatJson::decode( $value, true ); |
184 | 177 | unset( $options[$option] ); |
185 | 178 | } |
186 | 179 | } |
187 | 180 | |
| 181 | + //Record preferences for each gadget |
| 182 | + $gadgets = Gadget::loadList(); |
188 | 183 | foreach ( $gadgets as $gadget ) { |
189 | | - $prefsDescription = $gadget->getPrefsDescription(); |
190 | | - |
191 | | - if ( $prefsDescription === null ) { |
192 | | - continue; |
| 184 | + if ( isset( $preferencesCache[$gadget->getName()] ) ) { |
| 185 | + if ( $gadget->getPrefsDescription() !== null ) { |
| 186 | + if ( isset( $preferencesCache[$gadget->getName()] ) ) { |
| 187 | + $userPrefs = $preferencesCache[$gadget->getName()]; |
| 188 | + } |
| 189 | + |
| 190 | + if ( !isset( $userPrefs ) ) { |
| 191 | + $userPrefs = array(); //no saved prefs (or invalid JSON), use defaults |
| 192 | + } |
| 193 | + |
| 194 | + Gadget::matchPrefsWithDescription( $gadget->getPrefsDescription(), $userPrefs ); |
| 195 | + |
| 196 | + $gadget->setPrefs( $userPrefs ); |
| 197 | + } |
193 | 198 | } |
194 | | - |
195 | | - if ( isset( $existingPrefs[$gadget->getName()] ) ) { |
196 | | - $userPrefs = FormatJson::decode( $existingPrefs[$gadget->getName()], true ); |
197 | | - } |
198 | | - |
199 | | - if ( !isset( $userPrefs ) ) { |
200 | | - $userPrefs = array(); //no saved prefs, use defaults |
201 | | - } |
202 | | - |
203 | | - Gadget::matchPrefsWithDescription( $prefsDescription, $userPrefs ); |
204 | | - |
205 | | - $gadget->setPrefs( $userPrefs ); |
206 | 199 | } |
207 | 200 | |
208 | 201 | return true; |
— | — | @@ -291,15 +284,10 @@ |
292 | 285 | $resourceLoaded = false, |
293 | 286 | $requiredRights = array(), |
294 | 287 | $onByDefault = false, |
295 | | - $category; |
| 288 | + $category, |
| 289 | + $preferences = null; |
296 | 290 | |
297 | 291 | |
298 | | - //Map from gadget names to preferences of current user. |
299 | | - //This is needed because gadget preferences are retrieved and saved |
300 | | - //in UserLoadOptions and UserSaveOptions hooks handlers instead than |
301 | | - //in Gadget class constructor. |
302 | | - private static $preferencesCache = array(); |
303 | | - |
304 | 292 | //Syntax specifications of preference description language |
305 | 293 | private static $prefsDescriptionSpecifications = array( |
306 | 294 | 'boolean' => array( |
— | — | @@ -736,6 +724,7 @@ |
737 | 725 | return true; // empty array |
738 | 726 | } |
739 | 727 | |
| 728 | + |
740 | 729 | /** |
741 | 730 | * Loads list of gadgets and returns it as associative array of sections with gadgets |
742 | 731 | * e.g. array( 'sectionnname1' => array( $gadget1, $gadget2), |
— | — | @@ -748,14 +737,30 @@ |
749 | 738 | global $wgMemc; |
750 | 739 | |
751 | 740 | static $gadgets = null; |
752 | | - if ( $gadgets !== null && $forceNewText === null ) return $gadgets; |
| 741 | + |
| 742 | + if ( $gadgets !== null && $forceNewText === null ) { |
| 743 | + return $gadgets; |
| 744 | + } |
753 | 745 | |
754 | 746 | wfProfileIn( __METHOD__ ); |
| 747 | + |
| 748 | + $user = RequestContext::getMain()->getUser(); |
| 749 | + if ( $user->isLoggedIn() ) { |
| 750 | + //Force loading user options |
| 751 | + //HACK: this may lead to loadStructuredList being recursively called. |
| 752 | + $user->getOptions(); |
| 753 | + |
| 754 | + //Check again, loadStructuredList may have been called from UserLoadOptions hook handler; |
| 755 | + //in that case, we should just return current value instead of rebuilding the list again. |
| 756 | + //TODO: is there a better design? |
| 757 | + if ( $gadgets !== null && $forceNewText === null ) { |
| 758 | + wfProfileOut( __METHOD__ ); |
| 759 | + return $gadgets; |
| 760 | + } |
| 761 | + } |
| 762 | + |
755 | 763 | $key = wfMemcKey( 'gadgets-definition', self::GADGET_CLASS_VERSION ); |
756 | 764 | |
757 | | - //Force loading user options |
758 | | - RequestContext::getMain()->getUser()->getOptions(); |
759 | | - |
760 | 765 | if ( $forceNewText === null ) { |
761 | 766 | //cached? |
762 | 767 | $gadgets = $wgMemc->get( $key ); |
— | — | @@ -905,7 +910,7 @@ |
906 | 911 | //Check if a preference is valid, according to description |
907 | 912 | //NOTE: we pass both $prefs and $prefName (instead of just $prefs[$prefName]) |
908 | 913 | // to allow checking for null. |
909 | | - private static function checkSinglePref( &$prefDescription, &$prefs, $prefName ) { |
| 914 | + private static function checkSinglePref( $prefDescription, $prefs, $prefName ) { |
910 | 915 | |
911 | 916 | //isset( $prefs[$prefName] ) would return false for null values |
912 | 917 | if ( !array_key_exists( $prefName, $prefs ) ) { |
— | — | @@ -1034,8 +1039,7 @@ |
1035 | 1040 | * @return Mixed the array of preferences if they have been set, null otherwise. |
1036 | 1041 | */ |
1037 | 1042 | public function getPrefs() { |
1038 | | - $prefs = self::$preferencesCache[$this->getName()]; |
1039 | | - return self::$preferencesCache[$this->getName()]; |
| 1043 | + return $this->preferences; |
1040 | 1044 | } |
1041 | 1045 | |
1042 | 1046 | /** |
— | — | @@ -1065,9 +1069,9 @@ |
1066 | 1070 | if ( !self::checkPrefsAgainstDescription( $prefsDescription, $prefs ) ) { |
1067 | 1071 | return false; //validation failed |
1068 | 1072 | } |
1069 | | - |
1070 | | - self::$preferencesCache[$this->getName()] = $prefs; |
1071 | 1073 | |
| 1074 | + $this->preferences = $prefs; |
| 1075 | + |
1072 | 1076 | if ( $savePrefs ) { |
1073 | 1077 | $user = RequestContext::getMain()->getUser(); |
1074 | 1078 | $user->saveSettings(); |
— | — | @@ -1115,7 +1119,6 @@ |
1116 | 1120 | } |
1117 | 1121 | |
1118 | 1122 | public function getScript( ResourceLoaderContext $context ) { |
1119 | | - |
1120 | 1123 | $prefs = $this->gadget->getPrefs(); |
1121 | 1124 | |
1122 | 1125 | //Enclose gadget's code in a closure, with "this" bound to the |
Index: branches/salvatoreingala/Gadgets/ApiGetGadgetPrefs.php |
— | — | @@ -32,6 +32,7 @@ |
33 | 33 | } |
34 | 34 | |
35 | 35 | $gadgetName = $params['gadget']; |
| 36 | + |
36 | 37 | $gadgets = Gadget::loadList(); |
37 | 38 | $gadget = $gadgets && isset( $gadgets[$gadgetName] ) ? $gadgets[$gadgetName] : null; |
38 | 39 | |
— | — | @@ -47,6 +48,10 @@ |
48 | 49 | |
49 | 50 | $userPrefs = $gadget->getPrefs(); |
50 | 51 | |
| 52 | + if ( $userPrefs === null ) { |
| 53 | + throw new MWException( __METHOD__ . ': $userPrefs should not be null.' ); |
| 54 | + } |
| 55 | + |
51 | 56 | //Add user preferences to preference description |
52 | 57 | foreach ( $userPrefs as $pref => $value ) { |
53 | 58 | $prefsDescription['fields'][$pref]['value'] = $value; |