Completed
Push — master ( 399dca...4d8d1d )
by Nazar
04:53
created

users::admin_users___search_get()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 11

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 15
rs 9.4285
cc 2
eloc 11
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\Response,
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 \cs\Request $Request
25
	 *
26
	 * @return array
27
	 *
28
	 * @throws ExitException
29
	 */
30
	static function admin_users___get ($Request) {
31
		$User    = User::instance();
32
		$columns = static::admin_users___search_options()['columns'];
33
		$id      = $Request->route_ids(0);
34
		$ids     = $Request->query('ids');
35
		$search  = $Request->query('search');
36
		if ($id) {
37
			$result = static::admin_users___get_post_process(
38
				$User->get($columns, $id)
39
			);
40
		} elseif ($ids) {
41
			$ids    = _int(explode(',', $ids));
42
			$result = [];
43
			foreach ($ids as $id) {
44
				$result[] = static::admin_users___get_post_process(
45
					$User->get($columns, $id)
46
				);
47
			}
48
		} elseif ($search) {
49
			$result = _int($User->search_users($search));
50
		} else {
51
			throw new ExitException(400);
52
		}
53
		if (!$result) {
54
			throw new ExitException(404);
55
		}
56
		return $result;
57
	}
58
	protected static function admin_users___get_post_process ($data) {
59
		$L                          = new Prefix('system_admin_users_');
60
		$data['reg_date_formatted'] = $data['reg_date'] ? date($L->_date, $data['reg_date']) : $L->undefined;
61
		$data['reg_ip_formatted']   = hex2ip($data['reg_ip'], 10);
62
		return $data;
63
	}
64
	/**
65
	 * Update user's data
66
	 *
67
	 * @param \cs\Request $Request
68
	 *
69
	 * @throws ExitException
70
	 */
71
	static function admin_users___patch ($Request) {
72
		$user_id = (int)$Request->route_ids(0);
73
		$user    = $Request->data('user');
74
		if (!$user_id || !$user) {
75
			throw new ExitException(400);
76
		}
77
		$User      = User::instance();
78
		$user_data = array_filter(
79
			$user,
80
			function ($item) {
81
				return in_array($item, ['login', 'username', 'email', 'language', 'timezone', 'status', 'block_until', 'avatar'], true);
82
			},
83
			ARRAY_FILTER_USE_KEY
84
		);
85
		foreach ($user_data as &$d) {
86
			$d = xap($d, false);
87
		}
88
		unset($d);
89
		if (!$user_data && !isset($user['password'])) {
90
			throw new ExitException(400);
91
		}
92
		$L = new Prefix('system_admin_users_');
93
		if (
94
			isset($user_data['login']) &&
95
			$user_data['login'] !== $User->get('login', $user_id) &&
96
			$User->get_id(hash('sha224', $user_data['login']))
97
		) {
98
			throw new ExitException($L->login_occupied, 400);
99
		}
100
		if (
101
			isset($user_data['email']) &&
102
			$user_data['email'] !== $User->get('email', $user_id) &&
103
			$User->get_id(hash('sha224', $user_data['email']))
104
		) {
105
			throw new ExitException($L->email_occupied, 400);
106
		}
107
		if (!$User->set($user_data, null, $user_id)) {
108
			throw new ExitException(500);
109
		}
110
		if (isset($user['password']) && !$User->set_password($user['password'], $user_id)) {
111
			throw new ExitException(500);
112
		}
113
	}
114
	/**
115
	 * Add new user
116
	 *
117
	 * @param \cs\Request $Request
118
	 *
119
	 * @return array
120
	 *
121
	 * @throws ExitException
122
	 */
123
	static function admin_users___post ($Request) {
124
		$User  = User::instance();
125
		$email = $Request->data('email');
126
		if (!$email) {
127
			throw new ExitException(400);
128
		}
129
		$result = $User->registration($email, false, false);
130
		if (!$result) {
131
			throw new ExitException(500);
132
		}
133
		if ($result === 'exists') {
134
			$L = new Prefix('system_admin_users_');
135
			throw new ExitException($L->user_already_exists, 400);
136
		}
137
		Response::instance()->code = 201;
138
		return [
139
			'login'    => $User->get('login', $result['id']),
140
			'password' => $result['password']
141
		];
142
	}
143
	/**
144
	 * Advanced search for users (users data will be returned similar to GET method)
145
	 *
146
	 * @param \cs\Request $Request
147
	 *
148
	 * @return array
1 ignored issue
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,array[]|int...eger[]|string|string[]>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
149
	 *
150
	 * @throws ExitException
151
	 */
152
	static function admin_users___search ($Request) {
153
		$options = $Request->data('mode', 'column', 'text', 'page', 'limit');
154
		if (!$options) {
155
			throw new ExitException(400);
156
		}
157
		$mode           = $options['mode'];
158
		$column         = $options['column'];
159
		$text           = $options['text'];
160
		$page           = (int)$options['page'];
161
		$limit          = (int)$options['limit'];
162
		$search_options = static::admin_users___search_options();
163
		if (
164
			!in_array($mode, $search_options['modes']) ||
165
			(
166
				$column !== '' &&
167
				!in_array($column, $search_options['columns'])
168
			)
169
		) {
170
			throw new ExitException(400);
171
		}
172
		$cdb   = User::instance()->db();
173
		$where = static::admin_users___search_prepare_where($mode, $text, $column ?: $search_options['columns'], $cdb);
174
		$count = $cdb->qfs(
175
			[
176
				"SELECT COUNT(`id`)
177
				FROM `[prefix]users`
178
				WHERE $where"
179
			]
180
		);
181
		if (!$count) {
182
			throw new ExitException(404);
183
		}
184
		$where = str_replace('%', '%%', $where);
185
		$ids   = $cdb->qfas(
186
			[
187
				"SELECT `id`
188
				FROM `[prefix]users`
189
				WHERE $where
190
				ORDER BY `id`
191
				LIMIT %d, %d",
192
				($page - 1) * $limit,
193
				$limit
194
			]
195
		);
196
		return [
197
			'count' => $count,
198
			'users' => static::admin_users___search_get($ids, $search_options['columns'])
199
		];
200
	}
201
	/**
202
	 * @param string           $mode
203
	 * @param string           $text
204
	 * @param string|string[]  $column
205
	 * @param \cs\DB\_Abstract $cdb
206
	 *
207
	 * @return string
208
	 */
209
	protected static function admin_users___search_prepare_where ($mode, $text, $column, $cdb) {
210
		$where = '1';
211
		if ($text && $mode) {
212
			switch ($mode) {
213
				case '=':
214
				case '!=':
215
				case '>':
216
				case '<':
217
				case '>=':
218
				case '<=':
219
				case 'LIKE':
220
				case 'NOT LIKE':
221
				case 'REGEXP':
222
				case 'NOT REGEXP':
223
					$where = static::admin_users___search_prepare_where_compose(
224
						"`%s` $mode %s",
225
						$column,
226
						$cdb->s($text)
227
					);
228
					break;
229
				case 'IN':
230
				case 'NOT IN':
231
					$where = static::admin_users___search_prepare_where_compose(
232
						"`%s` $mode (%s)",
233
						$column,
234
						implode(
235
							", ",
236
							$cdb->s(
237
								_trim(
238
									_trim(explode(',', $text), "'")
239
								)
240
							)
241
						)
242
					);
243
					break;
244
			}
245
		}
246
		return $where;
247
	}
248
	/**
249
	 * @param string          $where
250
	 * @param string|string[] $column
251
	 * @param string          $text
252
	 *
253
	 * @return string
254
	 */
255
	protected static function admin_users___search_prepare_where_compose ($where, $column, $text) {
256
		if (is_array($column)) {
257
			$return = [];
258
			foreach ($column as $c) {
259
				$return[] = sprintf($where, $c, $text);
260
			}
261
			return '('.implode(' OR ', $return).')';
262
		}
263
		return sprintf($where, $column, $text);
264
	}
265
	/**
266
	 * @param int[]    $users
267
	 * @param string[] $columns
268
	 *
269
	 * @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...
270
	 */
271
	protected static function admin_users___search_get ($users, $columns) {
272
		$User = User::instance();
273
		foreach ($users as &$user) {
274
			$groups         = (array)$User->get_groups($user);
275
			$user           =
276
				$User->get($columns, $user) +
277
				[
278
					'is_user'  => in_array(User::USER_GROUP_ID, $groups),
279
					'is_admin' => in_array(User::ADMIN_GROUP_ID, $groups),
280
					'username' => $User->username($user)
281
				];
282
			$user['reg_ip'] = hex2ip($user['reg_ip'], 10);
283
		}
284
		return $users;
285
	}
286
	/**
287
	 * Get available search options
288
	 *
289
	 * @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...
290
	 */
291
	static function admin_users___search_options () {
292
		return [
293
			'modes'   => [
294
				'=',
295
				'!=',
296
				'>',
297
				'<',
298
				'>=',
299
				'<=',
300
				'LIKE',
301
				'NOT LIKE',
302
				'IN',
303
				'NOT IN',
304
				'IS NULL',
305
				'IS NOT NULL',
306
				'REGEXP',
307
				'NOT REGEXP'
308
			],
309
			'columns' => array_values(
310
				array_filter(
311
					User::instance()->get_users_columns(),
312
					function ($column) {
313
						return $column !== 'password_hash';
314
					}
315
				)
316
			)
317
		];
318
	}
319
}
320