source: trunk/common/db/user.php @ 1184

Revision 1155, 7.5 KB checked in by adrian.budau, 6 months ago (diff)

Avatar Optimization

This is an optimization for managing avatars on the server. Because
there are only 5 sizes used on all the site it's more useful to resize
all of the images to those 5(thus increasing the space usage by less
than 100%) and when a client asks for a size give it directly rather
then resizing all the time. The 5 sizes are tiny (old L16x16),
small(old L32x32), normal(old L50x50), forum(old L75xL75, used only on

the forum at the moment), big(old 100x100) and full(the original picture).


To get the avatar on a size from the server simply use the page
avatar/%some_size%/%some_user where %some_user% is a username and
%some_size$ is a one the 5 sizes. In case the user doesn't exists or he
doesn't have an avatar we use a placeholder image. If the size given is
not from the list or is omitted the server return a classic
404 Error(File not found)

The script which resizes the image for the current users is called
make-avatar-folder found in the scripts folder. It requires the attach
folder to have permission for read and write.

The setup has also been modified so fresh installes will work without
calling the script.

Reviewboard Link: http://reviewboard.infoarena.ro/r/176/

  • Property svn:eol-style set to native
Line 
1<?php
2
3require_once(IA_ROOT_DIR."common/db/db.php");
4require_once(IA_ROOT_DIR."common/db/smf.php");
5require_once(IA_ROOT_DIR."common/user.php");
6require_once(IA_ROOT_DIR."common/cache.php");
7//require_once(IA_ROOT_DIR."common/db/tags.php");
8
9// Add an user to the cache, or update if already there.
10// Nothing happens if null is passed.
11//
12// Query functions can use this safely, it will just ignore nulls.
13// Always returns $user.
14function _user_cache_add($user) {
15    if (!is_null($user)) {
16        log_assert_valid(user_validate($user));
17        mem_cache_set("user-by-name:{$user['username']}", $user);
18        mem_cache_set("user-by-id:{$user['id']}", $user);
19    }
20    return $user;
21}
22
23// Delete an user from the cache. $user must be a valid user.
24function _user_cache_delete($user) {
25    log_assert_valid(user_validate($user));
26    mem_cache_delete("user-by-name:{$user['username']}");
27    mem_cache_delete("user-by-id:{$user['id']}");
28}
29
30// Test password in IA1 format.
31function user_test_ia1_password($username, $password)
32{
33    // old ia1 users are expected to have the ia1 hashed password
34    // as their actual password
35    $password = db_query_value(sprintf("SELECT PASSWORD('%s')",
36                                       db_escape($password)));
37    // hash password ia2 style
38    $password = user_hash_password($password, $username);
39    // test
40    $query = sprintf("SELECT *
41                      FROM ia_user
42                      WHERE username = '%s' AND '%s' = `password`",
43                     db_escape($username), db_escape($password));
44
45    return _user_cache_add(db_fetch($query));
46}
47
48// Check user's password.
49// Returns user struct or null if user/passwrd is wrong.
50function user_test_password($username, $password)
51{
52    // Query database
53    $hash = user_hash_password($password, $username);
54    $query = sprintf("SELECT *
55                      FROM ia_user
56                      WHERE username = %s AND `password` = %s",
57                     db_quote($username), db_quote($hash));
58    $user = db_fetch($query);
59
60    // Store in cache
61    return _user_cache_add(db_fetch($query));
62}
63
64// Get user by email. Returns valid user or null.
65function user_get_by_email($email)
66{
67    // Query database.
68    $query = sprintf("SELECT *
69                      FROM ia_user
70                      WHERE email = '%s'",
71                     db_escape($email));
72    $user = db_fetch($query);
73
74    // Store in cache if not null.
75    return _user_cache_add(db_fetch($query));
76}
77
78// Get user by username. Returns valid user or null.
79function user_get_by_username($user_name)
80{
81    // Check the cache.
82    if (($res = mem_cache_get("user-by-name:$user_name")) !== false) {
83        return $res;
84    }
85
86    // Query database.
87    $query = sprintf("SELECT *
88                      FROM ia_user
89                      WHERE username = '%s'",
90                     db_escape($user_name));
91    $user = db_fetch($query);
92
93    // Keep in cache.
94    // If we didn't find an user we store a null in the cache by hand.
95    if ($user !== null) {
96        return _user_cache_add($user);
97    } else {
98        mem_cache_set("user-by-name:$user_name", null);
99        return null;
100    }
101}
102
103// Get an user struct by his numeric id.
104// Remarkably similar to user_get_by_username.
105function user_get_by_id($user_id)
106{
107    // Check the cache.
108    if (($res = mem_cache_get("user-by-id:$user_id")) !== false) {
109        return $res;
110    }
111
112    // Query database
113    $query = sprintf("SELECT *
114                      FROM ia_user
115                      WHERE id = %s",
116                     db_quote($user_id));
117    $user = db_fetch($query);
118
119    // Keep in cache
120    if ($user !== null) {
121        return _user_cache_add($user);
122    } else {
123        mem_cache_set("user-by-id:$user_id", null);
124        return null;
125    }
126
127}
128
129// Create a new user.
130// This also creates an user page and SMF user.
131// $user must be a valid user struct, user_id ignored
132// Returns created $user or throws up on error.
133function user_create($user, $remote_ip_info=null)
134{
135    log_assert_valid(user_validate($user));
136
137    // DB magic.
138    unset($user['id']);
139    db_insert("ia_user", $user);
140    $user['id'] = db_insert_id();
141
142    // Check db magic
143    // FIXME: do we really need this?
144    _user_cache_delete($user);
145    $new_user = user_get_by_username($user['username']);
146    log_assert($new_user, "Failed creating user");
147
148    // Create user page.
149    require_once(IA_ROOT_DIR . "common/textblock.php");
150    $replace = array("user_id" => $user['username']);
151    textblock_copy_replace("template/newuser", IA_USER_TEXTBLOCK_PREFIX.$user['username'],
152                           $replace, "public", $new_user['id'], $remote_ip_info);
153
154    // Create SMF user
155    require_once(IA_ROOT_DIR."common/db/smf.php");
156    $smf_id = smf_create_user($user);
157    log_assert($smf_id, "SMF user for {$user['username']} not created.");
158
159    // Cache and return
160    return _user_cache_add($new_user);
161}
162
163// Update user information.
164// $user should be a complete user struct.
165// Uses db_update evilness.
166// Also updates SMF, which is good.
167function user_update($user)
168{
169    log_assert_valid(user_validate($user));
170
171    // Update DB
172    db_update("ia_user", $user, "id = ".db_quote($user['id']));
173
174    // Update SMF
175    smf_update_user($user);
176
177    _user_cache_add($user);
178}
179
180// Returns array with *all* registered usernames.
181// FIXME: grep and exterminate.
182function user_get_list($all_fields = false) {
183    $rows = db_fetch_all("SELECT * FROM `ia_user`");
184    $users = array();
185    foreach ($rows as $row) {
186        if ($all_fields) {
187            $users[$row['username']] = $row;
188        }
189        else {
190            $users[] = $row['username'];
191        }
192    }
193    return $users;
194}
195
196// Get all users.
197// Do not fucking use.
198function user_get_all() {
199    return db_fetch_all("SELECT * FROM `ia_user`");
200}
201
202// Counts number of users, cached.
203function user_count() {
204    if (($res = mem_cache_get("total-user-count")) !== false) {
205        return $res;
206    }
207    $result = db_query_value("SELECT COUNT(*) FROM ia_user");
208    return mem_cache_set("total-user-count", $result);
209}
210
211// Returns array with user submitted tasks. Filter tasks by choosing whether
212// to select failed and solved tasks.
213function user_submitted_tasks($user_id, $solved = true, $failed = true) {
214    // construct where
215    if ($solved && $failed) {
216        // no condition
217        $where = '';
218    }
219    elseif ($solved) {
220        $where = 'AND ia_score_user_round_task.score = 100';
221    }
222    elseif ($failed) {
223        $where = 'AND ia_score_user_round_task.score < 100';
224    }
225    else {
226        // This shouldn't happen
227        log_error('You can\'t select nothing.');
228    }
229
230    $query = sprintf("SELECT *
231        FROM ia_score_user_round_task
232        LEFT JOIN ia_task ON ia_task.id = ia_score_user_round_task.task_id
233        WHERE ia_score_user_round_task.user_id = '%s'
234              AND ia_score_user_round_task.round_id = 'arhiva' AND NOT ia_task.id IS NULL %s
235        GROUP BY ia_task.id
236        ORDER BY ia_task.`order`", $user_id, $where);
237
238    return db_fetch_all($query);
239}
240
241// Returns array with rounds that user has submitted to tasks.
242function user_submitted_rounds($user_id) {
243    // FIXME: Find a way to remove the hard-coded "<> 'arhiva'"
244    $query = "SELECT *
245        FROM ia_score_user_round_task
246        LEFT JOIN ia_round ON ia_round.id = ia_score_user_round_task.round_id
247        WHERE ia_score_user_round_task.user_id = '%s'
248              AND NOT ia_round.id IS NULL AND ia_round.id <> 'arhiva'
249        GROUP BY ia_round.id";
250    $query = sprintf($query, $user_id);
251
252    return db_fetch_all($query);
253}
254
255?>
Note: See TracBrowser for help on using the repository browser.