/[drupal]/contributions/modules/user_stats/user_stats.module
ViewVC logotype

Contents of /contributions/modules/user_stats/user_stats.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.2 - (show annotations) (download) (as text)
Sun Nov 4 19:51:36 2007 UTC (2 years ago) by liammcdermott
Branch: MAIN
CVS Tags: HEAD
Branch point for: DRUPAL-5
Changes since 1.1: +9 -16 lines
File MIME type: text/x-php
Don't store $user objects in a static array. Load each time instead.
1 <?php
2 // $Id$
3
4 /**
5 * Returns user stats
6 *
7 * @param $type
8 * The statistic to return. Possible values are:
9 * - "reg_days"
10 * - "join_date"
11 * - "login_days"
12 * - "last_post"
13 * - "post_count"
14 * @param $uid
15 * The user id who's stats should be retrieved.
16 *
17 * @return
18 * The statistic requested. Every statistic except join_date and onlin is a numeric.
19 * Join date is a string, whilst online is a boolean.
20 */
21 function user_stats_get_stats($type, $uid) {
22 $user = user_load(array('uid' => $uid));
23 switch ($type) {
24 case 'reg_days':
25 return floor((time() - $user->created) / 86400);
26 case 'join_date':
27 return $user->created;
28 case 'login_days':
29 return floor((time() - $user->access) / 86400);
30 case 'post_days':
31 return floor((time() - _user_stats_last_post($user)) / 86400);
32 case 'post_count':
33 // If the post count for this user hasn't been set then update it
34 if (!isset($user->user_post_count)) {
35 user_stats_post_count_update($user, 'reset');
36 }
37 return $user->user_post_count;
38 case 'online':
39 return (round((time() - $user->access) / 60) < 15 ? TRUE : FALSE);
40 }
41 }
42
43 /**
44 * Drupal hook implementations
45 */
46
47 /**
48 * Implementation of hook_nodeapi()
49 *
50 * Increments post count on insert or publish
51 * Decrements post count on delete or unpublish
52 * Checks and updates users without post counts on view
53 *
54 * @param &$node
55 * The node the action is being performed on.
56 * @param $op
57 * The operation being performed. We are interested in insert, delete, update and view
58 */
59 function user_stats_nodeapi(&$node, $op) {
60 switch ($op) {
61 case 'insert':
62 $user = user_load(array('uid' => $node->uid));
63 if ($node->status) {
64 user_stats_post_count_update($user, 'increment');
65 }
66 break;
67 case 'delete':
68 $user = user_load(array('uid' => $node->uid));
69 user_stats_post_count_update($user, 'decrement');
70 break;
71 case 'update':
72 $user = user_load(array('uid' => $node->uid));
73 // Can't think of any other way of doing this than resetting the user...
74 user_stats_post_count_update($user, 'reset');
75 break;
76 }
77 }
78
79 /**
80 * Implementation of hook_comment()
81 *
82 * Increments post count on insert or publish
83 * Decrements post count on delete or unpublish
84 * Updates users with no post count on view
85 *
86 * @param $a1
87 * Either the form values being submitted, the module form to be displayed,
88 * or the comment object.
89 * @param $op
90 * What kind of action is being performed.
91 */
92 function user_stats_comment(&$a1, $op) {
93 $comment = (object)$a1;
94
95 switch ($op) {
96 case 'insert':
97 case 'publish':
98 $user = user_load(array('uid' => $comment->uid));
99 user_stats_post_count_update($user, 'increment');
100 break;
101 case 'delete':
102 case 'unpublish':
103 $user = user_load(array('uid' => $comment->uid));
104 user_stats_post_count_update($user, 'decrement');
105 break;
106 }
107 }
108
109 /**
110 * Implementation of hook_cron()
111 *
112 * We slowly work through all users without a post count
113 * updating them.
114 */
115 function user_stats_cron() {
116 if (variable_get('user_stats_rebuild_stats', TRUE)) {
117 $sql = "SELECT fid FROM {profile_fields} WHERE name='user_post_count'";
118 $fid = db_result(db_query($sql));
119
120 // Unfortunately this cannot be done with a JOIN because of the need to match on fid
121 $sql = "SELECT uid FROM {users} WHERE uid NOT IN ( ";
122 $sql .= " SELECT uid FROM {profile_values} ";
123 $sql .= " WHERE fid=%d ";
124 $sql .= ") ";
125 // Update 25 users per cron run
126 $result = db_query_range($sql, $fid, 0, 25);
127 // If all users have been updated we'll avoid running this expensive
128 // query again by setting the following flag!
129 if (db_num_rows($result) == 0) {
130 variable_set('user_stats_rebuild_stats', FALSE);
131 }
132 while ($update_user = db_fetch_object($result)) {
133 $user = user_load($update_user);
134 user_stats_post_count_update($user, 'reset');
135 }
136 }
137 // Fire workflow_ng daily anniversary event
138 if (module_exists('workflow_ng')) {
139 $sql = "SELECT uid FROM {users} u ";
140 // ((last cron - created) - (time() - created)) > one day
141 $sql .= "WHERE ";
142 $sql .= "(FLOOR((unix_timestamp()-created)/(60*60*24))-FLOOR((%d-created)/(60*60*24)))>0 ";
143 $sql .= "AND uid>0 ";
144 $result = db_query($sql, variable_get('cron_last', time()));
145 while ($update_user = db_fetch_object($result)) {
146 $user = user_load($update_user);
147 workflow_ng_invoke_event('user_stats_day_older', $user);
148 }
149 }
150 }
151
152 /**
153 * Helper function to get the last post created by the user.
154 *
155 * @param $account
156 * User object.
157 *
158 * @return
159 * Unix timestamp: date of the last post (node or comment).
160 */
161 function _user_stats_last_post($account) {
162 $sql = "SELECT MAX(created) FROM {node} WHERE uid=%d";
163 $max_node = db_result(db_query($sql, $account->uid));
164 $sql = "SELECT MAX(timestamp) FROM {comments} WHERE uid=%d";
165 $max_comments = db_result(db_query($sql, $account->uid));
166
167 if ($max_node > $max_comments) {
168 return $max_node;
169 }
170 else {
171 return $max_comments;
172 }
173 }
174
175 /**
176 * Workflow-ng hooks and implementing functions
177 */
178
179 /**
180 * Implementation of hook_event_info()
181 */
182 function user_stats_event_info() {
183 return array(
184 'user_stats_post_count_increment' => array(
185 '#label' => t('User post count incremented'),
186 '#arguments' => array(
187 'user' => array('#entity' => 'user', '#label' => t('User whos post count has incremented')),
188 ),
189 '#module' => t('User'),
190 ),
191 'user_stats_post_count_decrement' => array(
192 '#label' => t('User post count decremented'),
193 '#arguments' => array(
194 'user' => array('#entity' => 'user', '#label' => t('User whos post count has decremented')),
195 ),
196 '#module' => t('User'),
197 ),
198 'user_stats_post_count_reset' => array(
199 '#label' => t('User post count reset'),
200 '#arguments' => array(
201 'user' => array('#entity' => 'user', '#label' => t('User whos post count has reset')),
202 ),
203 '#module' => t('User'),
204 ),
205 'user_stats_day_older' => array(
206 '#label' => t('User is a day older'),
207 '#arguments' => array(
208 'user' => array('#entity' => 'user', '#label' => t('User who is a day older')),
209 ),
210 '#module' => t('User'),
211 ),
212 );
213 }
214
215 /**
216 * Implementation of hook_action_info()
217 */
218 function user_stats_action_info() {
219 return array(
220 'user_stats_action_post_count_increment' => array(
221 '#label' => t('Increment user post count'),
222 '#arguments' => array(
223 'user' => array('#entity' => 'user', '#label' => t('User whos post count should be incremented')),
224 ),
225 '#module' => t('User'),
226 '#description' => t('Increments the post count of a user'),
227 ),
228 'user_stats_action_post_count_decrement' => array(
229 '#label' => t('Decrement user post count'),
230 '#arguments' => array(
231 'user' => array('#entity' => 'user', '#label' => t('User whos post count should be decremented')),
232 ),
233 '#module' => t('User'),
234 '#description' => t('Decrements the post count of a user'),
235 ),
236 'user_stats_action_post_count_reset' => array(
237 '#label' => t('Reset the user post count'),
238 '#arguments' => array(
239 'user' => array('#entity' => 'user', '#label' => t('User whos post count should be reset')),
240 ),
241 '#module' => t('User'),
242 '#description' => t('Resets the post count of the current user.'),
243 ),
244 );
245 }
246
247 /**
248 * hook_action_info() callback
249 *
250 * @param &$user
251 * Reference to the user object
252 * @param $settings
253 * Workflow-ng settings parameter
254 * @param &$arguments
255 * Pointer to all arguments passed to the function from Workflow-ng
256 * @param &$log
257 * Reference to Workflow-ng's internal log
258 */
259 function user_stats_action_post_count_increment(&$user, $settings, &$arguments, &$log) {
260 user_stats_post_count_update($user, 'increment');
261 }
262
263 /**
264 * hook_action_info() callback
265 *
266 * @param &$user
267 * Reference to the user object
268 * @param $settings
269 * Workflow-ng settings parameter
270 * @param &$arguments
271 * Pointer to all arguments passed to the function from Workflow-ng
272 * @param &$log
273 * Reference to Workflow-ng's internal log
274 */
275 function user_stats_action_post_count_decrement(&$user, $settings, &$arguments, &$log) {
276 user_stats_post_count_update($user, 'decrement');
277 }
278
279 /**
280 * hook_action_info() callback
281 *
282 * @param &$user
283 * Reference to the user object
284 * @param $settings
285 * Workflow-ng settings parameter
286 * @param &$arguments
287 * Pointer to all arguments passed to the function from Workflow-ng
288 * @param &$log
289 * Reference to Workflow-ng's internal log
290 */
291 function user_stats_action_post_count_reset(&$user, $settings, &$arguments, &$log) {
292 user_stats_post_count_update($user, 'reset');
293 }
294
295 /**
296 * Token hook implementations
297 */
298
299
300 /**
301 * Implementation of hook_token_values()
302 */
303 function user_stats_token_values($type, $object = NULL) {
304 switch ($type) {
305 case 'user':
306 // Get the user object
307 if (isset($object)) {
308 $account = (object)$object;
309 } else {
310 global $user;
311 $account = user_load(array('uid' => $user->uid));
312 }
313 // If post count for the user hasn't been generated then update it
314 if(!isset($account->user_post_count)) {
315 user_stats_post_count_update($account, 'reset');
316 }
317
318 $last_post = _user_stats_last_post($account);
319 $values['reg-days'] = floor((time()-$account->created) / 86400);
320 $values['login-days'] = floor((time()-$account->access) / 86400);
321 $values['post-days'] = floor((time()-$last_post) / 86400);
322 $values['post-count'] = $account->user_post_count;
323 break;
324 }
325
326 return $values;
327 }
328
329 /**
330 * Implementation of hook_token_list()
331 */
332 function user_stats_token_list($type = 'all') {
333 if ($type == 'user' || $type == 'all') {
334 $tokens['user']['reg-days'] = t('Number of days since the user registered');
335 $tokens['user']['login-days'] = t('Number of days since the user logged in');
336 $tokens['user']['post-days'] = t('Number of days since the user posted');
337 $tokens['user']['post-count'] = t('User\'s post count');
338 }
339 return $tokens;
340 }
341
342 /**
343 * Manage the post count of a given user
344 *
345 * @param $user
346 * Reference to user object
347 * @param $op
348 * Whether the user post count should be incremented, decremented, or reset.
349 * The default is to increment. Possible values are:
350 * 'increment' (default)
351 * 'decrement'
352 * 'reset'
353 */
354 function user_stats_post_count_update(&$user, $op = 'increment') {
355 // The lock stops infinite recursions, the action will still happen, but the
356 // corresponding event (the reason for an infinite loop) will not be fired
357 static $locked;
358 // Shared SQL for increment and decrement
359 $sql = "UPDATE {profile_values} INNER JOIN {profile_fields} ON ";
360 $sql .= "{profile_values}.fid={profile_fields}.fid ";
361 $sql .= "SET VALUE=%d WHERE name='user_post_count' AND uid=%d ";
362
363 switch ($op) {
364 case 'increment':
365 if (!isset($user->user_post_count)) {
366 $user = user_stats_post_count_update($user, 'reset');
367 }
368 else {
369 $user->user_post_count++;
370 db_query($sql, $user->user_post_count, $user->uid);
371 // We use $locked to stop infinite loops
372 if (!$locked && module_exists('workflow_ng')) {
373 $locked = TRUE;
374 workflow_ng_invoke_event('user_stats_post_count_increment', $user);
375 $locked = FALSE;
376 }
377 }
378 break;
379 case 'decrement':
380 if (!isset($user->user_post_count)) {
381 $user = user_stats_post_count_update($user, 'reset');
382 }
383 else {
384 $user->user_post_count--;
385 db_query($sql, $user->user_post_count, $user->uid);
386 if (!$locked && module_exists('workflow_ng')) {
387 $locked = TRUE;
388 workflow_ng_invoke_event('user_stats_post_count_decrement', $user);
389 $locked = FALSE;
390 }
391 }
392 break;
393 case 'reset':
394 static $fid;
395 if (!isset($fid)) {
396 $sql = "SELECT fid FROM {profile_fields} WHERE name='user_post_count'";
397 $fid = db_result(db_query($sql));
398 }
399 $sql = "SELECT COUNT(*) FROM {node} WHERE uid=%d AND status<>0";
400 $node_count = db_result(db_query($sql, $user->uid));
401 $sql = "SELECT COUNT(*) FROM {comments} WHERE uid=%d AND status=0";
402 $comments_count = db_result(db_query($sql, $user->uid));
403 $total_count = $node_count + $comments_count;
404 $sql = "DELETE {profile_values} FROM {profile_values} ";
405 $sql .= "WHERE fid=%d AND uid=%d";
406 db_query($sql, $fid, $user->uid);
407 $sql = "INSERT IGNORE INTO {profile_values} (fid, uid, value) VALUES ( ";
408 $sql .= "%d, %d, %d ";
409 $sql .= ") ";
410 db_query($sql, $fid, $user->uid, $total_count);
411 if (!$locked && module_exists('workflow_ng')) {
412 $locked = TRUE;
413 workflow_ng_invoke_event('user_stats_post_count_reset', $user);
414 $locked = FALSE;
415 }
416 break;
417 }
418 // Reload the user post count
419 $user = user_load(array('uid' => $account->uid));
420 }

  ViewVC Help
Powered by ViewVC 1.1.2