Merge "Add ss_active_users in SiteStats::isSane"
[mediawiki.git] / resources / mediawiki / mediawiki.user.js
blob9fd2e5e45941c130a728a4a34bb5b5079828be98
1 /*
2  * Implementation for mediaWiki.user
3  */
5 ( function ( mw, $ ) {
7         /**
8          * User object
9          */
10         function User( options, tokens ) {
11                 var user, callbacks;
13                 /* Private Members */
15                 user = this;
16                 callbacks = {};
18                 /**
19                  * Gets the current user's groups or rights.
20                  * @param {String} info: One of 'groups' or 'rights'.
21                  * @param {Function} callback
22                  */
23                 function getUserInfo( info, callback ) {
24                         var api;
25                         if ( callbacks[info] ) {
26                                 callbacks[info].add( callback );
27                                 return;
28                         }
29                         callbacks.rights = $.Callbacks('once memory');
30                         callbacks.groups = $.Callbacks('once memory');
31                         callbacks[info].add( callback );
32                         api = new mw.Api();
33                         api.get( {
34                                 action: 'query',
35                                 meta: 'userinfo',
36                                 uiprop: 'rights|groups'
37                         } ).always( function ( data ) {
38                                 var rights, groups;
39                                 if ( data.query && data.query.userinfo ) {
40                                         rights = data.query.userinfo.rights;
41                                         groups = data.query.userinfo.groups;
42                                 }
43                                 callbacks.rights.fire( rights || [] );
44                                 callbacks.groups.fire( groups || [] );
45                         } );
46                 }
48                 /* Public Members */
50                 this.options = options || new mw.Map();
52                 this.tokens = tokens || new mw.Map();
54                 /* Public Methods */
56                 /**
57                  * Generates a random user session ID (32 alpha-numeric characters).
58                  *
59                  * This information would potentially be stored in a cookie to identify a user during a
60                  * session or series of sessions. Its uniqueness should not be depended on.
61                  *
62                  * @return String: Random set of 32 alpha-numeric characters
63                  */
64                 this.generateRandomSessionId = function () {
65                         var i, r,
66                                 id = '',
67                                 seed = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
68                         for ( i = 0; i < 32; i++ ) {
69                                 r = Math.floor( Math.random() * seed.length );
70                                 id += seed.substring( r, r + 1 );
71                         }
72                         return id;
73                 };
75                 /**
76                  * Gets the current user's name.
77                  *
78                  * @return Mixed: User name string or null if users is anonymous
79                  */
80                 this.getName = function () {
81                         return mw.config.get( 'wgUserName' );
82                 };
84                 /**
85                  * @deprecated since 1.20 use mw.user.getName() instead
86                  */
87                 this.name = function () {
88                         return this.getName();
89                 };
91                 /**
92                  * Get date user registered, if available.
93                  *
94                  * @return {Date|false|null} date user registered, or false for anonymous users, or
95                  *  null when data is not available
96                  */
97                 this.getRegistration = function () {
98                         var registration = mw.config.get( 'wgUserRegistration' );
99                         if ( this.isAnon() ) {
100                                 return false;
101                         } else if ( registration === null ) {
102                                 // Information may not be available if they signed up before
103                                 // MW began storing this.
104                                 return null;
105                         } else {
106                                 return new Date( registration );
107                         }
108                 };
110                 /**
111                  * Checks if the current user is anonymous.
112                  *
113                  * @return Boolean
114                  */
115                 this.isAnon = function () {
116                         return user.getName() === null;
117                 };
119                 /**
120                  * @deprecated since 1.20 use mw.user.isAnon() instead
121                  */
122                 this.anonymous = function () {
123                         return user.isAnon();
124                 };
126                 /**
127                  * Gets a random session ID automatically generated and kept in a cookie.
128                  *
129                  * This ID is ephemeral for everyone, staying in their browser only until they close
130                  * their browser.
131                  *
132                  * @return String: User name or random session ID
133                  */
134                 this.sessionId = function () {
135                         var sessionId = $.cookie( 'mediaWiki.user.sessionId' );
136                         if ( typeof sessionId === 'undefined' || sessionId === null ) {
137                                 sessionId = user.generateRandomSessionId();
138                                 $.cookie( 'mediaWiki.user.sessionId', sessionId, { 'expires': null, 'path': '/' } );
139                         }
140                         return sessionId;
141                 };
143                 /**
144                  * Gets the current user's name or the session ID
145                  *
146                  * @return {string} User name or random session ID
147                  */
148                 this.id = function () {
149                         var name = user.getName();
150                         if ( name ) {
151                                 return name;
152                         }
153                         return user.sessionId();
154                 };
156                 /**
157                  * Gets the user's bucket, placing them in one at random based on set odds if needed.
158                  *
159                  * @param key String: Name of bucket
160                  * @param options Object: Bucket configuration options
161                  * @param options.buckets Object: List of bucket-name/relative-probability pairs (required,
162                  * must have at least one pair)
163                  * @param options.version Number: Version of bucket test, changing this forces rebucketing
164                  * (optional, default: 0)
165                  * @param options.expires Number: Length of time (in days) until the user gets rebucketed
166                  * (optional, default: 30)
167                  * @return String: Bucket name - the randomly chosen key of the options.buckets object
168                  *
169                  * @example
170                  *     mw.user.bucket( 'test', {
171                  *         'buckets': { 'ignored': 50, 'control': 25, 'test': 25 },
172                  *         'version': 1,
173                  *         'expires': 7
174                  *     } );
175                  */
176                 this.bucket = function ( key, options ) {
177                         var cookie, parts, version, bucket,
178                                 range, k, rand, total;
180                         options = $.extend( {
181                                 buckets: {},
182                                 version: 0,
183                                 expires: 30
184                         }, options || {} );
186                         cookie = $.cookie( 'mediaWiki.user.bucket:' + key );
188                         // Bucket information is stored as 2 integers, together as version:bucket like: "1:2"
189                         if ( typeof cookie === 'string' && cookie.length > 2 && cookie.indexOf( ':' ) > 0 ) {
190                                 parts = cookie.split( ':' );
191                                 if ( parts.length > 1 && Number( parts[0] ) === options.version ) {
192                                         version = Number( parts[0] );
193                                         bucket = String( parts[1] );
194                                 }
195                         }
196                         if ( bucket === undefined ) {
197                                 if ( !$.isPlainObject( options.buckets ) ) {
198                                         throw 'Invalid buckets error. Object expected for options.buckets.';
199                                 }
200                                 version = Number( options.version );
201                                 // Find range
202                                 range = 0;
203                                 for ( k in options.buckets ) {
204                                         range += options.buckets[k];
205                                 }
206                                 // Select random value within range
207                                 rand = Math.random() * range;
208                                 // Determine which bucket the value landed in
209                                 total = 0;
210                                 for ( k in options.buckets ) {
211                                         bucket = k;
212                                         total += options.buckets[k];
213                                         if ( total >= rand ) {
214                                                 break;
215                                         }
216                                 }
217                                 $.cookie(
218                                         'mediaWiki.user.bucket:' + key,
219                                         version + ':' + bucket,
220                                         { 'path': '/', 'expires': Number( options.expires ) }
221                                 );
222                         }
223                         return bucket;
224                 };
226                 /**
227                  * Gets the current user's groups.
228                  */
229                 this.getGroups = function ( callback ) {
230                         getUserInfo( 'groups', callback );
231                 };
233                 /**
234                  * Gets the current user's rights.
235                  */
236                 this.getRights = function ( callback ) {
237                         getUserInfo( 'rights', callback );
238                 };
239         }
241         // Extend the skeleton mw.user from mediawiki.js
242         // This is kind of ugly but we're stuck with this for b/c reasons
243         mw.user = new User( mw.user.options, mw.user.tokens );
245 }( mediaWiki, jQuery ) );