Merge "(bug 12701) Use diff of all unseen revisions in the "new messages" bar."
[lhc/web/wiklou.git] / resources / mediawiki / mediawiki.user.js
1 /*
2 * Implementation for mediaWiki.user
3 */
4
5 ( function ( $ ) {
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, { 'expires': 365, 'path': '/' } );
142 return id;
143 };
144
145 /**
146 * Gets the user's bucket, placing them in one at random based on set odds if needed.
147 *
148 * @param key String: Name of bucket
149 * @param options Object: Bucket configuration options
150 * @param options.buckets Object: List of bucket-name/relative-probability pairs (required,
151 * must have at least one pair)
152 * @param options.version Number: Version of bucket test, changing this forces rebucketing
153 * (optional, default: 0)
154 * @param options.tracked Boolean: Track the event of bucketing through the API module of
155 * the ClickTracking extension (optional, default: false)
156 * @param options.expires Number: Length of time (in days) until the user gets rebucketed
157 * (optional, default: 30)
158 * @return String: Bucket name - the randomly chosen key of the options.buckets object
159 *
160 * @example
161 * mw.user.bucket( 'test', {
162 * 'buckets': { 'ignored': 50, 'control': 25, 'test': 25 },
163 * 'version': 1,
164 * 'tracked': true,
165 * 'expires': 7
166 * } );
167 */
168 this.bucket = function( key, options ) {
169 options = $.extend( {
170 'buckets': {},
171 'version': 0,
172 'tracked': false,
173 'expires': 30
174 }, options || {} );
175 var cookie = $.cookie( 'mediaWiki.user.bucket:' + key );
176 var bucket = null;
177 var version = 0;
178 // Bucket information is stored as 2 integers, together as version:bucket like: "1:2"
179 if ( typeof cookie === 'string' && cookie.length > 2 && cookie.indexOf( ':' ) > 0 ) {
180 var parts = cookie.split( ':' );
181 if ( parts.length > 1 && parts[0] == options.version ) {
182 version = Number( parts[0] );
183 bucket = String( parts[1] );
184 }
185 }
186 if ( bucket === null ) {
187 if ( !$.isPlainObject( options.buckets ) ) {
188 throw 'Invalid buckets error. Object expected for options.buckets.';
189 }
190 version = Number( options.version );
191 // Find range
192 var range = 0, k;
193 for ( k in options.buckets ) {
194 range += options.buckets[k];
195 }
196 // Select random value within range
197 var rand = Math.random() * range;
198 // Determine which bucket the value landed in
199 var total = 0;
200 for ( k in options.buckets ) {
201 bucket = k;
202 total += options.buckets[k];
203 if ( total >= rand ) {
204 break;
205 }
206 }
207 if ( options.tracked ) {
208 mw.loader.using( 'jquery.clickTracking', function() {
209 $.trackAction(
210 'mediaWiki.user.bucket:' + key + '@' + version + ':' + bucket
211 );
212 } );
213 }
214 $.cookie(
215 'mediaWiki.user.bucket:' + key,
216 version + ':' + bucket,
217 { 'path': '/', 'expires': Number( options.expires ) }
218 );
219 }
220 return bucket;
221 };
222
223 /**
224 * Gets the current user's groups.
225 */
226 this.getGroups = function ( callback ) {
227 getUserInfo( 'groups', callback );
228 };
229
230 /**
231 * Gets the current user's rights.
232 */
233 this.getRights = function ( callback ) {
234 getUserInfo( 'rights', callback );
235 };
236 }
237
238 // Extend the skeleton mw.user from mediawiki.js
239 // This is kind of ugly but we're stuck with this for b/c reasons
240 mw.user = new User( mw.user.options, mw.user.tokens );
241
242 }( jQuery ) );