Merge "Follow-up I0b781c11 (2a55449): use User::getAutomaticGroups()."
[lhc/web/wiklou.git] / resources / mediawiki / mediawiki.user.js
1 /*
2 * Implementation for mediaWiki.user
3 */
4
5 ( function ( mw, $ ) {
6
7 /**
8 * User object
9 */
10 function User( options, tokens ) {
11
12 /* Private Members */
13
14 var that = this;
15 var callbacks = {};
16
17 /**
18 * Gets the current user's groups or rights.
19 * @param {String} info: One of 'groups' or 'rights'.
20 * @param {Function} callback
21 */
22 function getUserInfo( info, callback ) {
23 var api;
24 if ( callbacks[info] ) {
25 callbacks[info].add( callback );
26 return;
27 }
28 callbacks.rights = $.Callbacks('once memory');
29 callbacks.groups = $.Callbacks('once memory');
30 callbacks[info].add( callback );
31 api = new mw.Api();
32 api.get( {
33 action: 'query',
34 meta: 'userinfo',
35 uiprop: 'rights|groups'
36 } ).always( function ( data ) {
37 var rights, groups;
38 if ( data.query && data.query.userinfo ) {
39 rights = data.query.userinfo.rights;
40 groups = data.query.userinfo.groups;
41 }
42 callbacks.rights.fire( rights || [] );
43 callbacks.groups.fire( groups || [] );
44 } );
45 }
46
47 /* Public Members */
48
49 this.options = options || new mw.Map();
50
51 this.tokens = tokens || new mw.Map();
52
53 /* Public Methods */
54
55 /**
56 * Generates a random user session ID (32 alpha-numeric characters).
57 *
58 * This information would potentially be stored in a cookie to identify a user during a
59 * session or series of sessions. Its uniqueness should not be depended on.
60 *
61 * @return String: Random set of 32 alpha-numeric characters
62 */
63 function generateId() {
64 var id = '';
65 var seed = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
66 for ( var i = 0, r; i < 32; i++ ) {
67 r = Math.floor( Math.random() * seed.length );
68 id += seed.substring( r, r + 1 );
69 }
70 return id;
71 }
72
73 /**
74 * Gets the current user's name.
75 *
76 * @return Mixed: User name string or null if users is anonymous
77 */
78 this.getName = function () {
79 return mw.config.get( 'wgUserName' );
80 };
81
82 /**
83 * @deprecated since 1.20 use mw.user.getName() instead
84 */
85 this.name = function () {
86 return this.getName();
87 };
88
89 /**
90 * Checks if the current user is anonymous.
91 *
92 * @return Boolean
93 */
94 this.isAnon = function () {
95 return that.getName() === null;
96 };
97
98 /**
99 * @deprecated since 1.20 use mw.user.isAnon() instead
100 */
101 this.anonymous = function () {
102 return that.isAnon();
103 };
104
105 /**
106 * Gets a random session ID automatically generated and kept in a cookie.
107 *
108 * This ID is ephemeral for everyone, staying in their browser only until they close
109 * their browser.
110 *
111 * @return String: User name or random session ID
112 */
113 this.sessionId = function () {
114 var sessionId = $.cookie( 'mediaWiki.user.sessionId' );
115 if ( typeof sessionId === 'undefined' || sessionId === null ) {
116 sessionId = generateId();
117 $.cookie( 'mediaWiki.user.sessionId', sessionId, { 'expires': null, 'path': '/' } );
118 }
119 return sessionId;
120 };
121
122 /**
123 * Gets the current user's name or a random ID automatically generated and kept in a cookie.
124 *
125 * This ID is persistent for anonymous users, staying in their browser up to 1 year. The
126 * expiration time is reset each time the ID is queried, so in most cases this ID will
127 * persist until the browser's cookies are cleared or the user doesn't visit for 1 year.
128 *
129 * @return String: User name or random session ID
130 */
131 this.id = function() {
132 var name = that.getName();
133 if ( name ) {
134 return name;
135 }
136 var id = $.cookie( 'mediaWiki.user.id' );
137 if ( typeof id === 'undefined' || id === null ) {
138 id = generateId();
139 }
140 // Set cookie if not set, or renew it if already set
141 $.cookie( 'mediaWiki.user.id', id, {
142 expires: 365,
143 path: '/'
144 } );
145 return id;
146 };
147
148 /**
149 * Gets the user's bucket, placing them in one at random based on set odds if needed.
150 *
151 * @param key String: Name of bucket
152 * @param options Object: Bucket configuration options
153 * @param options.buckets Object: List of bucket-name/relative-probability pairs (required,
154 * must have at least one pair)
155 * @param options.version Number: Version of bucket test, changing this forces rebucketing
156 * (optional, default: 0)
157 * @param options.tracked Boolean: Track the event of bucketing through the API module of
158 * the ClickTracking extension (optional, default: false)
159 * @param options.expires Number: Length of time (in days) until the user gets rebucketed
160 * (optional, default: 30)
161 * @return String: Bucket name - the randomly chosen key of the options.buckets object
162 *
163 * @example
164 * mw.user.bucket( 'test', {
165 * 'buckets': { 'ignored': 50, 'control': 25, 'test': 25 },
166 * 'version': 1,
167 * 'tracked': true,
168 * 'expires': 7
169 * } );
170 */
171 this.bucket = function ( key, options ) {
172 options = $.extend( {
173 'buckets': {},
174 'version': 0,
175 'tracked': false,
176 'expires': 30
177 }, options || {} );
178 var cookie = $.cookie( 'mediaWiki.user.bucket:' + key );
179 var bucket = null;
180 var version = 0;
181 // Bucket information is stored as 2 integers, together as version:bucket like: "1:2"
182 if ( typeof cookie === 'string' && cookie.length > 2 && cookie.indexOf( ':' ) > 0 ) {
183 var parts = cookie.split( ':' );
184 if ( parts.length > 1 && Number( parts[0] ) === options.version ) {
185 version = Number( parts[0] );
186 bucket = String( parts[1] );
187 }
188 }
189 if ( bucket === null ) {
190 if ( !$.isPlainObject( options.buckets ) ) {
191 throw 'Invalid buckets error. Object expected for options.buckets.';
192 }
193 version = Number( options.version );
194 // Find range
195 var range = 0, k;
196 for ( k in options.buckets ) {
197 range += options.buckets[k];
198 }
199 // Select random value within range
200 var rand = Math.random() * range;
201 // Determine which bucket the value landed in
202 var total = 0;
203 for ( k in options.buckets ) {
204 bucket = k;
205 total += options.buckets[k];
206 if ( total >= rand ) {
207 break;
208 }
209 }
210 if ( options.tracked ) {
211 mw.loader.using( 'jquery.clickTracking', function () {
212 $.trackAction(
213 'mediaWiki.user.bucket:' + key + '@' + version + ':' + bucket
214 );
215 } );
216 }
217 $.cookie(
218 'mediaWiki.user.bucket:' + key,
219 version + ':' + bucket,
220 { 'path': '/', 'expires': Number( options.expires ) }
221 );
222 }
223 return bucket;
224 };
225
226 /**
227 * Gets the current user's groups.
228 */
229 this.getGroups = function ( callback ) {
230 getUserInfo( 'groups', callback );
231 };
232
233 /**
234 * Gets the current user's rights.
235 */
236 this.getRights = function ( callback ) {
237 getUserInfo( 'rights', callback );
238 };
239 }
240
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 );
244
245 }( mediaWiki, jQuery ) );