Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
76 / 76
100.00% covered (success)
100.00%
10 / 10
CRAP
100.00% covered (success)
100.00%
1 / 1
base
100.00% covered (success)
100.00%
76 / 76
100.00% covered (success)
100.00%
10 / 10
22
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 set_user
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 after_ban
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 after_unban
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 check
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 tidy
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 get_banned_users
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 get_ban_options
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
1
 get_excluded
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
4
 logout_affected_users
100.00% covered (success)
100.00%
42 / 42
100.00% covered (success)
100.00%
1 / 1
10
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\ban\type;
15
16use phpbb\db\driver\driver_interface;
17
18abstract class base implements type_interface
19{
20    /** @var driver_interface */
21    protected $db;
22
23    /** @var array */
24    protected $excluded;
25
26    /** @var string */
27    protected $bans_table;
28
29    /** @var string */
30    protected $sessions_keys_table;
31
32    /** @var string */
33    protected $sessions_table;
34
35    /** @var \phpbb\user */
36    protected $user;
37
38    /** @var string */
39    protected $users_table;
40
41    /**
42     * Creates a ban type.
43     *
44     * @param driver_interface    $db                        A phpBB DBAL object
45     * @param string            $bans_table                The bans table
46     * @param string            $users_table            The users table
47     * @param string            $sessions_table            The sessions table
48     * @param string            $sessions_keys_table    The sessions keys table
49     */
50    public function __construct(driver_interface $db, string $bans_table, string $users_table, string $sessions_table, string $sessions_keys_table)
51    {
52        $this->db = $db;
53        $this->bans_table = $bans_table;
54        $this->users_table = $users_table;
55        $this->sessions_table = $sessions_table;
56        $this->sessions_keys_table = $sessions_keys_table;
57    }
58
59    /**
60     * {@inheritDoc}
61     */
62    public function set_user(\phpbb\user $user): void
63    {
64        $this->user = $user;
65    }
66
67    /**
68     * {@inheritDoc}
69     */
70    public function after_ban(array $data): array
71    {
72        return $this->logout_affected_users($data['items']);
73    }
74
75    /**
76     * {@inheritDoc}
77     */
78    public function after_unban(array $data): array
79    {
80        return [];
81    }
82
83    /**
84     * {@inheritDoc}
85     */
86    public function check(array $ban_rows, array $user_data)
87    {
88        return false;
89    }
90
91    /**
92     * {@inheritDoc}
93     */
94    public function tidy(): void
95    {
96    }
97
98    /**
99     * {@inheritDoc}
100     */
101    public function get_banned_users(): array
102    {
103        return [];
104    }
105
106    /**
107     * {@inheritDoc}
108     */
109    public function get_ban_options(): array
110    {
111        $sql = 'SELECT *
112            FROM ' . $this->bans_table . '
113            WHERE (ban_end >= ' . time() . "
114                    OR ban_end = 0)
115                AND ban_mode = '{$this->db->sql_escape($this->get_type())}'
116            ORDER BY ban_item";
117        $result = $this->db->sql_query($sql);
118        $rowset = $this->db->sql_fetchrowset($result);
119        $this->db->sql_freeresult($result);
120
121        return $rowset;
122    }
123
124    /**
125     * Queries users that are excluded from banning (like founders)
126     * from the database and saves them in $this->excluded array.
127     * Returns true on success and false on failure
128     *
129     * @return bool
130     */
131    protected function get_excluded(): bool
132    {
133        $user_column = $this->get_user_column();
134        if (empty($user_column))
135        {
136            return false;
137        }
138
139        $this->excluded = [];
140
141        if (!empty($this->user))
142        {
143            $this->excluded[$this->user->id()] = $this->user->data[$user_column];
144        }
145
146        $sql = "SELECT user_id, {$this->db->sql_escape($user_column)}
147            FROM {$this->users_table}
148            WHERE user_type = " . USER_FOUNDER;
149        $result = $this->db->sql_query($sql);
150
151        while ($row = $this->db->sql_fetchrow($result))
152        {
153            $this->excluded[(int) $row['user_id']] = $row[$user_column];
154        }
155        $this->db->sql_freeresult($result);
156
157        return true;
158    }
159
160    /**
161     * Logs out all affected users in the given array. The values
162     * have to match the values of the column returned by get_user_column().
163     * Returns all banned users.
164     *
165     * @param array $ban_items
166     *
167     * @return array Logged out users
168     */
169    protected function logout_affected_users(array $ban_items): array
170    {
171        $user_column = $this->get_user_column();
172
173        if (empty($user_column))
174        {
175            return [];
176        }
177
178        if ($user_column !== 'user_id')
179        {
180            $ban_items_sql = [];
181            $ban_like_items = [];
182            foreach ($ban_items as $ban_item)
183            {
184                if (stripos($ban_item, '*') === false)
185                {
186                    $ban_items_sql[] = $ban_item;
187                }
188                else
189                {
190                    $ban_like_items[] = [$user_column, 'LIKE', str_replace('*', $this->db->get_any_char(), $ban_item)];
191                }
192            }
193
194            $sql_array = [
195                'SELECT'    => 'user_id',
196                'FROM'        => [
197                    $this->users_table    => '',
198                ],
199                'WHERE'        => ['AND',
200                    [
201                        ['OR',
202                            array_merge([
203                                [$user_column, 'IN', $ban_items_sql]
204                            ], $ban_like_items),
205                        ],
206                        ['user_id', 'NOT_IN', array_map('intval', array_keys($this->excluded))],
207                    ],
208                ],
209            ];
210            $sql = $this->db->sql_build_query('SELECT', $sql_array);
211            $result = $this->db->sql_query($sql);
212
213            $user_ids = [];
214            while ($row = $this->db->sql_fetchrow($result))
215            {
216                $user_ids[] = (int) $row['user_id'];
217            }
218            $this->db->sql_freeresult($result);
219        }
220        else
221        {
222            $user_ids = array_map('intval', $ban_items);
223        }
224
225        if (!empty($user_ids) && !empty($this->sessions_table))
226        {
227            $sql = 'DELETE FROM ' . $this->sessions_table . '
228                WHERE ' . $this->db->sql_in_set('session_user_id', $user_ids);
229            $this->db->sql_query($sql);
230        }
231        if (!empty($user_ids) && !empty($this->sessions_keys_table))
232        {
233            $sql = 'DELETE FROM ' . $this->sessions_keys_table . '
234                WHERE ' . $this->db->sql_in_set('user_id', $user_ids);
235            $this->db->sql_query($sql);
236        }
237
238        return $user_ids;
239    }
240}