Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
93.22% covered (success)
93.22%
55 / 59
57.14% covered (warning)
57.14%
4 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
user_loader
93.22% covered (success)
93.22%
55 / 59
57.14% covered (warning)
57.14%
4 / 7
19.11
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 load_users
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
3
 load_user_by_username
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
2
 get_user
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
5
 get_username
66.67% covered (warning)
66.67%
2 / 3
0.00% covered (danger)
0.00%
0 / 1
2.15
 get_avatar
88.89% covered (warning)
88.89%
8 / 9
0.00% covered (danger)
0.00%
0 / 1
2.01
 get_rank
85.71% covered (warning)
85.71%
12 / 14
0.00% covered (danger)
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
14namespace 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*/
24class 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 &amp;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}