Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
93.22% |
55 / 59 |
|
57.14% |
4 / 7 |
CRAP | |
0.00% |
0 / 1 |
user_loader | |
93.22% |
55 / 59 |
|
57.14% |
4 / 7 |
19.11 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
1 | |||
load_users | |
100.00% |
12 / 12 |
|
100.00% |
1 / 1 |
3 | |||
load_user_by_username | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
2 | |||
get_user | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
5 | |||
get_username | |
66.67% |
2 / 3 |
|
0.00% |
0 / 1 |
2.15 | |||
get_avatar | |
88.89% |
8 / 9 |
|
0.00% |
0 / 1 |
2.01 | |||
get_rank | |
85.71% |
12 / 14 |
|
0.00% |
0 / 1 |
4.05 |
1 | <?php |
2 | /** |
3 | * |
4 | * This file is part of the phpBB Forum Software package. |
5 | * |
6 | * @copyright (c) phpBB Limited <https://www.phpbb.com> |
7 | * @license GNU General Public License, version 2 (GPL-2.0) |
8 | * |
9 | * For full copyright and license information, please see |
10 | * the docs/CREDITS.txt file. |
11 | * |
12 | */ |
13 | |
14 | namespace phpbb; |
15 | |
16 | /** |
17 | * User loader class |
18 | * |
19 | * This handles loading users from the database and |
20 | * storing in them in a temporary cache so we do not |
21 | * have to query the same user multiple times in |
22 | * different services. |
23 | */ |
24 | class user_loader |
25 | { |
26 | /** @var \phpbb\avatar\helper */ |
27 | protected $avatar_helper; |
28 | |
29 | /** @var \phpbb\db\driver\driver_interface */ |
30 | protected $db = null; |
31 | |
32 | /** @var string */ |
33 | protected $phpbb_root_path = null; |
34 | |
35 | /** @var string */ |
36 | protected $php_ext = null; |
37 | |
38 | /** @var string */ |
39 | protected $users_table = null; |
40 | |
41 | /** |
42 | * Users loaded from the DB |
43 | * |
44 | * @var array Array of user data that we've loaded from the DB |
45 | */ |
46 | protected $users = array(); |
47 | |
48 | /** |
49 | * User loader constructor |
50 | * |
51 | * @param \phpbb\avatar\helper $avatar_helper Avatar helper object |
52 | * @param \phpbb\db\driver\driver_interface $db A database connection |
53 | * @param string $phpbb_root_path Path to the phpbb includes directory. |
54 | * @param string $php_ext php file extension |
55 | * @param string $users_table The name of the database table (phpbb_users) |
56 | */ |
57 | public function __construct(\phpbb\avatar\helper $avatar_helper, \phpbb\db\driver\driver_interface $db, $phpbb_root_path, $php_ext, $users_table) |
58 | { |
59 | $this->avatar_helper = $avatar_helper; |
60 | $this->db = $db; |
61 | |
62 | $this->phpbb_root_path = $phpbb_root_path; |
63 | $this->php_ext = $php_ext; |
64 | |
65 | $this->users_table = $users_table; |
66 | } |
67 | |
68 | /** |
69 | * Load user helper |
70 | * |
71 | * @param array $user_ids |
72 | * @param array $ignore_types user types to ignore |
73 | */ |
74 | public function load_users(array $user_ids, array $ignore_types = array()) |
75 | { |
76 | $user_ids[] = ANONYMOUS; |
77 | |
78 | // Make user_ids unique and convert to integer. |
79 | $user_ids = array_map('intval', array_unique($user_ids)); |
80 | |
81 | // Do not load users we already have in $this->users |
82 | $user_ids = array_diff($user_ids, array_keys($this->users)); |
83 | |
84 | if (count($user_ids)) |
85 | { |
86 | $sql = 'SELECT * |
87 | FROM ' . $this->users_table . ' |
88 | WHERE ' . $this->db->sql_in_set('user_id', $user_ids) . ' |
89 | AND ' . $this->db->sql_in_set('user_type', $ignore_types, true, true); |
90 | $result = $this->db->sql_query($sql); |
91 | |
92 | while ($row = $this->db->sql_fetchrow($result)) |
93 | { |
94 | $this->users[$row['user_id']] = $row; |
95 | } |
96 | $this->db->sql_freeresult($result); |
97 | } |
98 | } |
99 | |
100 | /** |
101 | * Load a user by username |
102 | * |
103 | * Stores the full data in the user cache so they do not need to be loaded again |
104 | * Returns the user id so you may use get_user() from the returned value |
105 | * |
106 | * @param string $username Raw username to load (will be cleaned) |
107 | * @return int User ID for the username |
108 | */ |
109 | public function load_user_by_username($username) |
110 | { |
111 | $sql = 'SELECT * |
112 | FROM ' . $this->users_table . " |
113 | WHERE username_clean = '" . $this->db->sql_escape(utf8_clean_string($username)) . "'"; |
114 | $result = $this->db->sql_query($sql); |
115 | $row = $this->db->sql_fetchrow($result); |
116 | $this->db->sql_freeresult($result); |
117 | |
118 | if ($row) |
119 | { |
120 | $this->users[$row['user_id']] = $row; |
121 | |
122 | return $row['user_id']; |
123 | } |
124 | |
125 | return ANONYMOUS; |
126 | } |
127 | |
128 | /** |
129 | * Get a user row from our users cache |
130 | * |
131 | * @param int $user_id User ID of the user you want to retrieve |
132 | * @param bool $query Should we query the database if this user has not yet been loaded? |
133 | * Typically this should be left as false and you should make sure |
134 | * you load users ahead of time with load_users() |
135 | * @return array|false Row from the database of the user or Anonymous if the user wasn't loaded/does not exist |
136 | * or bool False if the anonymous user was not loaded |
137 | */ |
138 | public function get_user(int $user_id, bool $query = false) |
139 | { |
140 | if (isset($this->users[$user_id])) |
141 | { |
142 | return $this->users[$user_id]; |
143 | } |
144 | // Query them if we must (if ANONYMOUS is sent as the user_id and we have not loaded Anonymous yet, we must load Anonymous as a last resort) |
145 | else if ($query || $user_id == ANONYMOUS) |
146 | { |
147 | $this->load_users(array($user_id)); |
148 | |
149 | return $user_id != ANONYMOUS ? $this->get_user($user_id) : $this->users[$user_id] ?? false; |
150 | } |
151 | |
152 | return $this->get_user(ANONYMOUS); |
153 | } |
154 | |
155 | /** |
156 | * Get username |
157 | * |
158 | * @param int $user_id User ID of the user you want to retrieve the username for |
159 | * @param string $mode The mode to load (same as get_username_string). One of the following: |
160 | * profile (for getting an url to the profile) |
161 | * username (for obtaining the username) |
162 | * colour (for obtaining the user colour) |
163 | * full (for obtaining a html string representing a coloured link to the users profile) |
164 | * no_profile (the same as full but forcing no profile link) |
165 | * @param string|bool $guest_username Optional parameter to specify the guest username. It will be used in favor of the GUEST language variable then. |
166 | * @param string|bool $custom_profile_url Optional parameter to specify a profile url. The user id get appended to this url as &u={user_id} |
167 | * @param bool $query Should we query the database if this user has not yet been loaded? |
168 | * Typically this should be left as false and you should make sure |
169 | * you load users ahead of time with load_users() |
170 | * @return string |
171 | */ |
172 | public function get_username(int $user_id, string $mode, $guest_username = false, $custom_profile_url = false, bool $query = false): string |
173 | { |
174 | if (!($user = $this->get_user($user_id, $query))) |
175 | { |
176 | return ''; |
177 | } |
178 | |
179 | return get_username_string($mode, $user['user_id'], $user['username'], $user['user_colour'], $guest_username, $custom_profile_url); |
180 | } |
181 | |
182 | /** |
183 | * Get avatar |
184 | * |
185 | * @param int $user_id User ID of the user you want to retrieve the avatar for |
186 | * @param bool $query Should we query the database if this user has not yet been loaded? |
187 | * Typically this should be left as false and you should make sure |
188 | * you load users ahead of time with load_users() |
189 | * @param bool $lazy If true, will be lazy loaded (requires JS) |
190 | * @return array |
191 | */ |
192 | public function get_avatar($user_id, $query = false, $lazy = false) |
193 | { |
194 | if (!($user = $this->get_user($user_id, $query))) |
195 | { |
196 | return []; |
197 | } |
198 | |
199 | $row = [ |
200 | 'avatar' => $user['user_avatar'], |
201 | 'avatar_type' => $user['user_avatar_type'], |
202 | 'avatar_width' => $user['user_avatar_width'], |
203 | 'avatar_height' => $user['user_avatar_height'], |
204 | ]; |
205 | |
206 | return $this->avatar_helper->get_avatar($row, 'USER_AVATAR', false, $lazy); |
207 | } |
208 | |
209 | /** |
210 | * Get rank |
211 | * |
212 | * @param int $user_id User ID of the user you want to retrieve the rank for |
213 | * @param bool $query Should we query the database if this user has not yet been loaded? |
214 | * Typically this should be left as false and you should make sure |
215 | * you load users ahead of time with load_users() |
216 | * @return array Array with keys 'rank_title', 'rank_img', and 'rank_img_src' |
217 | */ |
218 | public function get_rank(int $user_id, bool $query = false): array |
219 | { |
220 | if (!($user = $this->get_user($user_id, $query))) |
221 | { |
222 | return []; |
223 | } |
224 | |
225 | if (!function_exists('phpbb_get_user_rank')) |
226 | { |
227 | include($this->phpbb_root_path . 'includes/functions_display.' . $this->php_ext); |
228 | } |
229 | |
230 | $rank = array( |
231 | 'rank_title', |
232 | 'rank_img', |
233 | 'rank_img_src', |
234 | ); |
235 | |
236 | $user_rank_data = phpbb_get_user_rank($user, ($user['user_id'] == ANONYMOUS ? false : $user['user_posts'])); |
237 | $rank['rank_title'] = $user_rank_data['title']; |
238 | $rank['rank_img'] = $user_rank_data['img']; |
239 | $rank['rank_img_src'] = $user_rank_data['img_src']; |
240 | |
241 | return $rank; |
242 | } |
243 | } |