Completed
Push — master ( ff9168...5fb3fd )
by Nazar
06:20
created

users::admin_users___search_get()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 16
Code Lines 12

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 16
rs 9.4285
cc 2
eloc 12
nc 2
nop 2
1
<?php
2
/**
3
 * @package    CleverStyle CMS
4
 * @subpackage System module
5
 * @category   modules
6
 * @author     Nazar Mokrynskyi <[email protected]>
7
 * @copyright  Copyright (c) 2015-2016, Nazar Mokrynskyi
8
 * @license    MIT License, see license.txt
9
 */
10
namespace cs\modules\System\api\Controller\admin;
11
use
12
	cs\ExitException,
13
	cs\Language\Prefix,
14
	cs\Page,
15
	cs\User;
16
17
trait users {
18
	/**
19
	 * Get user's data or data of several specified groups if specified in ids query parameter or allows to search for users by login or email (users id will
20
	 * be returned)
21
	 *
22
	 * Data will be pre-processed with `reg_date_formatted` and `reg_ip_formatted` keys added
23
	 *
24
	 * @param int[] $route_ids
25
	 *
26
	 * @throws ExitException
27
	 */
28
	static function admin_users___get ($route_ids) {
29
		$User    = User::instance();
30
		$Page    = Page::instance();
31
		$columns = static::admin_users___search_options_get()['columns'];
32
		if (isset($route_ids[0])) {
33
			$result = static::admin_users___get_post_process(
34
				$User->get($columns, $route_ids[0])
35
			);
36
		} elseif (isset($_GET['ids'])) {
37
			$ids    = _int(explode(',', $_GET['ids']));
38
			$result = [];
39
			foreach ($ids as $id) {
40
				$result[] = static::admin_users___get_post_process(
41
					$User->get($columns, $id)
42
				);
43
			}
44
		} elseif (isset($_GET['search'])) {
45
			$result = _int($User->search_users($_GET['search']));
46
		} else {
47
			throw new ExitException(400);
48
		}
49
		if (!$result) {
50
			throw new ExitException(404);
51
		}
52
		$Page->json($result);
53
	}
54
	protected static function admin_users___get_post_process ($data) {
55
		$L                          = new Prefix('system_admin_users_');
56
		$data['reg_date_formatted'] = $data['reg_date'] ? date($L->_date, $data['reg_date']) : $L->undefined;
57
		$data['reg_ip_formatted']   = hex2ip($data['reg_ip'], 10);
58
		return $data;
59
	}
60
	/**
61
	 * Update user's data
62
	 *
63
	 * @param int[] $route_ids
64
	 *
65
	 * @throws ExitException
66
	 */
67
	static function admin_users___patch ($route_ids) {
68
		if (!isset($route_ids[0], $_POST['user'])) {
69
			throw new ExitException(400);
70
		}
71
		$User    = User::instance();
72
		$user_id = (int)$route_ids[0];
73
		$is_bot  = in_array(User::BOT_GROUP_ID, $User->get_groups($user_id));
74
		if ($is_bot && !@$_POST['user']['login'] && !@$_POST['user']['email']) {
75
			throw new ExitException(400);
76
		}
77
		$columns_allowed_to_edit = $is_bot
78
			? ['login', 'username', 'email', 'status']
79
			: ['login', 'username', 'email', 'language', 'timezone', 'status', 'block_until', 'avatar'];
80
		$user_data               = array_filter(
81
			$_POST['user'],
82
			function ($item) use ($columns_allowed_to_edit) {
83
				return in_array($item, $columns_allowed_to_edit, true);
84
			},
85
			ARRAY_FILTER_USE_KEY
86
		);
87
		foreach ($user_data as &$d) {
88
			$d = xap($d, false);
89
		}
90
		unset($d);
91
		if (!$user_data && ($is_bot || !isset($_POST['user']['password']))) {
92
			throw new ExitException(400);
93
		}
94
		$L = new Prefix('system_admin_users_');
95
		if (
96
			isset($user_data['login']) &&
97
			$user_data['login'] !== $User->get('login', $user_id) &&
98
			$User->get_id(hash('sha224', $user_data['login']))
99
		) {
100
			throw new ExitException($L->login_occupied, 400);
101
		}
102
		if (
103
			isset($user_data['email']) &&
104
			$user_data['email'] !== $User->get('email', $user_id) &&
105
			$User->get_id(hash('sha224', $user_data['email']))
106
		) {
107
			throw new ExitException($L->email_occupied, 400);
108
		}
109
		if (!$User->set($user_data, null, $user_id)) {
110
			throw new ExitException(500);
111
		}
112
		if (!$is_bot && isset($_POST['user']['password']) && !$User->set_password($_POST['user']['password'], $user_id)) {
113
			throw new ExitException(500);
114
		}
115
	}
116
	/**
117
	 * Add new user or bot (different parameters required depending on `type` parameter)
118
	 *
119
	 * @throws ExitException
120
	 */
121
	static function admin_users___post () {
122
		if (!isset($_POST['type'])) {
123
			throw new ExitException(400);
124
		}
125
		$User = User::instance();
126
		$Page = Page::instance();
127
		if ($_POST['type'] === 'user' && isset($_POST['email'])) {
128
			$result = $User->registration($_POST['email'], false, false);
129
			if (!$result) {
130
				throw new ExitException(500);
131
			}
132
			if ($result === 'exists') {
133
				$L = new Prefix('system_admin_users_');
134
				throw new ExitException($L->user_already_exists, 400);
135
			}
136
			status_code(201);
137
			$Page->json(
138
				[
139
					'login'    => $User->get('login', $result['id']),
140
					'password' => $result['password']
141
				]
142
			);
143
		} elseif ($_POST['type'] === 'bot' && isset($_POST['name'], $_POST['user_agent'], $_POST['ip'])) {
144
			if ($User->add_bot($_POST['name'], $_POST['user_agent'], $_POST['ip'])) {
145
				status_code(201);
146
			} else {
147
				throw new ExitException(500);
148
			}
149
		} else {
150
			throw new ExitException(400);
151
		}
152
	}
153
	/**
154
	 * Advanced search for users (users data will be returned similar to GET method)
155
	 *
156
	 * @throws ExitException
157
	 */
158
	static function admin_users___search () {
159
		if (!isset($_POST['mode'], $_POST['column'], $_POST['text'], $_POST['page'], $_POST['limit'])) {
160
			throw new ExitException(400);
161
		}
162
		$mode           = $_POST['mode'];
163
		$column         = $_POST['column'];
164
		$text           = $_POST['text'];
165
		$page           = (int)$_POST['page'];
166
		$limit          = (int)$_POST['limit'];
167
		$search_options = static::admin_users___search_options_get();
168
		if (
169
			!in_array($mode, $search_options['modes']) ||
170
			(
171
				$column !== '' &&
172
				!in_array($column, $search_options['columns'])
173
			)
174
		) {
175
			throw new ExitException(400);
176
		}
177
		$cdb   = User::instance()->db();
178
		$where = static::admin_users___search_prepare_where($mode, $text, $column ?: $search_options['columns'], $cdb);
179
		$count = $cdb->qfs(
180
			[
181
				"SELECT COUNT(`id`)
182
				FROM `[prefix]users`
183
				WHERE $where"
184
			]
185
		);
186
		if (!$count) {
187
			throw new ExitException(404);
188
		}
189
		$where = str_replace('%', '%%', $where);
190
		$ids   = $cdb->qfas(
191
			[
192
				"SELECT `id`
193
				FROM `[prefix]users`
194
				WHERE $where
195
				ORDER BY `id`
196
				LIMIT %d, %d",
197
				($page - 1) * $limit,
198
				$limit
199
			]
200
		);
201
		Page::instance()->json(
202
			[
203
				'count' => $count,
204
				'users' => static::admin_users___search_get($ids, $search_options['columns'])
205
			]
206
		);
207
	}
208
	/**
209
	 * @param string           $mode
210
	 * @param string           $text
211
	 * @param string|string[]  $column
212
	 * @param \cs\DB\_Abstract $cdb
213
	 *
214
	 * @return string
215
	 */
216
	protected static function admin_users___search_prepare_where ($mode, $text, $column, $cdb) {
217
		$where = '1';
218
		if ($text && $mode) {
219
			switch ($mode) {
220
				case '=':
221
				case '!=':
222
				case '>':
223
				case '<':
224
				case '>=':
225
				case '<=':
226
				case 'LIKE':
227
				case 'NOT LIKE':
228
				case 'REGEXP':
229
				case 'NOT REGEXP':
230
					$where = static::admin_users___search_prepare_where_compose(
231
						"`%s` $mode %s",
232
						$column,
233
						$cdb->s($text)
234
					);
235
					break;
236
				case 'IN':
237
				case 'NOT IN':
238
					$where = static::admin_users___search_prepare_where_compose(
239
						"`%s` $mode (%s)",
240
						$column,
241
						implode(
242
							", ",
243
							$cdb->s(
244
								_trim(
245
									_trim(explode(',', $text), "'")
246
								)
247
							)
248
						)
249
					);
250
					break;
251
			}
252
		}
253
		return $where;
254
	}
255
	/**
256
	 * @param string          $where
257
	 * @param string|string[] $column
258
	 * @param string          $text
259
	 *
260
	 * @return string
261
	 */
262
	protected static function admin_users___search_prepare_where_compose ($where, $column, $text) {
263
		if (is_array($column)) {
264
			$return = [];
265
			foreach ($column as $c) {
266
				$return[] = sprintf($where, $c, $text);
267
			}
268
			return '('.implode(' OR ', $return).')';
269
		}
270
		return sprintf($where, $column, $text);
271
	}
272
	/**
273
	 * @param int[]    $users
274
	 * @param string[] $columns
275
	 *
276
	 * @return array[]
0 ignored issues
show
Documentation introduced by
Should the return type not be integer[]?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
277
	 */
278
	protected static function admin_users___search_get ($users, $columns) {
279
		$User = User::instance();
280
		foreach ($users as &$user) {
281
			$groups         = (array)$User->get_groups($user);
282
			$user           =
283
				$User->get($columns, $user) +
284
				[
285
					'is_user'  => in_array(User::USER_GROUP_ID, $groups),
286
					'is_bot'   => in_array(User::BOT_GROUP_ID, $groups),
287
					'is_admin' => in_array(User::ADMIN_GROUP_ID, $groups),
288
					'username' => $User->username($user)
289
				];
290
			$user['reg_ip'] = hex2ip($user['reg_ip'], 10);
291
		}
292
		return $users;
293
	}
294
	/**
295
	 * Get available search options
296
	 */
297
	static function admin_users___search_options () {
298
		Page::instance()->json(
299
			static::admin_users___search_options_get()
300
		);
301
	}
302
	/*
303
	 * @return string[][]
0 ignored issues
show
Documentation introduced by
Should the return type not be array<string,array>?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
304
	 */
305
	protected static function admin_users___search_options_get () {
306
		return [
307
			'modes'   => [
308
				'=',
309
				'!=',
310
				'>',
311
				'<',
312
				'>=',
313
				'<=',
314
				'LIKE',
315
				'NOT LIKE',
316
				'IN',
317
				'NOT IN',
318
				'IS NULL',
319
				'IS NOT NULL',
320
				'REGEXP',
321
				'NOT REGEXP'
322
			],
323
			'columns' => array_values(
324
				array_filter(
325
					User::instance()->get_users_columns(),
326
					function ($column) {
327
						return $column !== 'password_hash';
328
					}
329
				)
330
			)
331
		];
332
	}
333
}
334