scope('profile', _t('@users', 'Your Profile')) ->method('profile') ->scope('members-listing', _t('@users', 'Users List')) ->method('listing') ->method('ajax')->action('user-info') ->scope('admins-listing', _t('@users', 'Admins List')) ->method('listing_moderators') ->scope('users-edit', _t('@users', 'Users Management')) ->method('listing') ->action('mass', function () { return in_array($this->input->post('action'), [ 'block', 'unblock', 'unfake', 'delete', 'del_empty', ], true); }) ->methods(['user_add', 'user_edit', 'user_action']) ->method('ajax')->actions([ 'user-block', 'user-activate', 'user-admin-comment', 'auth-url', ]) ->scope('admins-edit', _t('@users', 'Admins Management')) ->publicMethod(['login','logout']) ->seoTemplates() ; } /** * Профиль пользователя * @return string|mixed */ public function profile() { if (! $this->haveAccessTo('profile')) { return $this->showAccessDenied(); } if (User::guest()) { return $this->adminRedirect(Errors::IMPOSSIBLE, 'login'); } $userID = User::id(); if ($this->isPOST()) { $changePassword = $this->input->post('changepass', TYPE_BOOL); $data = $this->model->userData($userID, ['password', 'password_salt']); $update = []; if ($this->errors->no() && $changePassword) { $passwordCurrent = $this->input->post('password0', TYPE_NOTRIM); # текущий пароль $passwordNew = $this->input->post('password1', TYPE_NOTRIM); # новый пароль $passwordRepeat = $this->input->post('password2', TYPE_NOTRIM); # новый пароль (подтверждение) do { if (!$passwordCurrent) { $this->errors->set(_t('@users', 'Enter current password'), 'password0'); break; } if (! $this->security->passwordCheck($passwordCurrent, $data['password'], $data['password_salt'])) { $this->errors->set(_t('@users', 'Current password is incorrect'), 'password0'); break; } if (empty($passwordNew) || mb_strlen($passwordNew) < $this->passwordMinLength) { $this->errors->set(_t('@users', 'New password is too short'), 'password1'); break; } if ($passwordNew !== $passwordRepeat) { $this->errors->set(_t('@users', 'Password confirmation failed'), 'password2'); break; } if ($this->errors->no()) { $update['password'] = $this->security->passwordHash($passwordNew, $data['password_salt']); } } while (false); } $msg = ''; if ($this->errors->no('users.admin.profile.submit', ['id' => $userID, 'data' => &$update]) && !empty($update)) { $this->model->userSave($userID, $update); $msg = _t('', 'Saved successfully'); } return $this->ajaxResponseForm(['msg' => $msg]); } $userGroups = $this->model->userGroups($userID); if (empty($userGroups)) { $userGroups = []; } $data = User::data(['name', 'login', 'avatar', 'email']); $data['user_id'] = $userID; $data['groups'] = $userGroups; return $this->template('admin/profile', $data); } /** * Выход из админ-панели * @return mixed */ public function logout() { $redirectUrl = Admin::url('users/login'); $this->app->hook('users.user.logout', User::id(), $redirectUrl); Auth::logout(); return $this->redirect($redirectUrl ?: '/'); } /** * Форма авторизации в адми-панель * @return mixed */ public function login() { if (User::admin()) { return $this->adminRedirect(null, 'profile'); } $login = ''; if ($this->isPOST()) { $login = $this->input->post('login', TYPE_STR); if (!$login) { $this->errors->set(_t('@users', 'Enter login')); } $password = $this->input->post('password', TYPE_NOTRIM); if (!$password) { $this->errors->set(_t('@users', 'Enter password')); } if ($this->errors->no('users.admin.login.step1', ['id' => 0, 'login' => $login, 'password' => $password])) { $this->isLoginOrEmail($login, $isEmail); $data = $this->model->userSessionData([($isEmail ? 'email' : 'login') => $login]); if (! empty($data)) { if (! $this->security->passwordCheck($password, $data['password'], $data['password_salt'])) { $data = false; } } if (! $data) { $this->errors->set(_t('@users', 'Incorrect login or password')); $userID = 0; } else { $userID = $data['id']; # аккаунт заблокирован if ($data['blocked'] == 1) { $this->errors->set(sprintf(_t('@users', 'Account suspended: %s'), $data['blocked_reason'])); } else { # проверка IP в бан-листе $isBlocked = $this->checkBan(); if ($isBlocked) { $this->errors->set(_t('@users', 'Access is blocked due to:
[reason]', [ 'reason' => $isBlocked, ])); } else { # проверка доступа в админ-панель if (! $this->model->userIsAdministrator($userID)) { $this->errors->accessDenied(); } } } } if ($this->errors->no('users.admin.login.step2', ['id' => $userID,'data' => &$data])) { if ($user = Auth::loginUsingId($userID)) { $user->touchOnLogin(); } $referer = $this->input->post('ref', TYPE_NOTAGS); $refererAdmin = Admin::url(); if ( ! empty($referer) && mb_stripos($referer, $refererAdmin) === 0 && $this->security->validateReferer($referer) ) { return $this->redirect($referer); } return $this->redirect($refererAdmin); } } } return Response::html( View::template('login', [ 'login' => $login, 'errors' => $this->errors->get(true), ]) ); } /** * Список пользователей * @return string|mixed */ public function listing() { if (! $this->haveAccessTo('members-listing')) { return $this->showAccessDenied(); } $mass = []; $massActions = [ 'unblock' => ['t' => _t('@users', 'Unblock'), 'access' => 'users-edit', 'tab' => [3]], 'unfake' => ['t' => _t('@users', 'Convert'), 'access' => 'users-edit', 'tab' => [5]], 'block' => ['t' => _t('@users', 'Block'), 'access' => 'users-edit', 'tab' => [1,2,5], 'params' => ['blocked_reason' => TYPE_STR]], 'delete' => ['t' => _t('@users', 'Delete'), 'access' => 'users-edit', 'tab' => [2,3,5], ], 'del_empty' => ['t' => _t('@users', 'Delete empty accounts'), 'access' => 'users-edit', 'tab' => [5], ], ]; foreach ($massActions as $k => $v) { if (! $this->haveAccessTo($v['access'])) { unset($massActions[$k]); } } $action = $this->input->get('act', TYPE_STR); if ($action) { $response = []; switch ($action) { case 'mass': $action = $this->input->post('action', TYPE_STR); if (! isset($massActions[$action])) { $this->errors->accessDenied(); break; } $a = $massActions[$action]; if (isset($a['alias']) && isset($massActions[ $a['alias'] ])) { $action = $a['alias']; $a = $massActions[$action]; } $mass['action'] = $action; if (isset($a['params'])) { $params = $this->input->postm($a['params']); $mass = array_merge($mass, $params); } break; } if (empty($mass)) { return $this->ajaxResponseForm($response); } } $f = $this->input->postgetm([ 'status' => TYPE_INT, # статус 'q' => TYPE_NOTAGS, # поиск по ID/login/email 'region' => TYPE_UINT, # страна / регион / город 'r_from' => TYPE_NOTAGS, # регистрация: от 'r_to' => TYPE_NOTAGS, # регистрация: до 'a_from' => TYPE_NOTAGS, # авторизация: от 'a_to' => TYPE_NOTAGS, # авторизация: до 'page' => TYPE_UINT, # страница ]); $filter = [':notSuperAdmin' => 'user_id != 1', 'admin' => 0]; if ($f['status'] > 0) { switch ($f['status']) { case 1: $filter['activated'] = 1; break; case 2: $filter['activated'] = 0; break; case 3: $filter['blocked'] = 1; break; case 4: $filter[':subscribed'] = 'enotify & ' . static::ENOTIFY_NEWS; $filter['blocked'] = 0; break; case 5: $filter['fake'] = 1; $filter['blocked'] = 0; break; } } if ($f['q'] != '') { $filter[':q'] = [ '( user_id = :q_user_id OR login LIKE :q_login OR email LIKE :q_email OR phone_number LIKE :q_email )', ':q_user_id' => intval($f['q']), ':q_login' => '%' . $f['q'] . '%', ':q_email' => '%' . $f['q'] . '%', ]; } if ($f['region'] > 0) { $regionData = Geo::regionData($f['region']); if (! empty($regionData['numlevel'])) { $filter['geo_region' . $regionData['numlevel']] = $f['region']; } } # период регистрации if (! empty($f['r_from'])) { $r_from = strtotime($f['r_from']); if (! empty($r_from)) { $filter[':regFrom'] = ['created >= :regFrom', ':regFrom' => date('Y-m-d', $r_from)]; } } if (! empty($f['r_to'])) { $r_to = strtotime($f['r_to']); if (! empty($r_to)) { $filter[':regTo'] = ['created <= :regTo', ':regTo' => date('Y-m-d', $r_to)]; } } # период последней авторизации if (! empty($f['a_from'])) { $a_from = strtotime($f['a_from']); if (!empty($a_from)) { $filter[':authFrom'] = ['last_login >= :authFrom', ':authFrom' => date('Y-m-d', $a_from)]; } } if (! empty($f['a_to'])) { $a_to = strtotime($f['a_to']); if (!empty($a_to)) { $filter[':authTo'] = ['last_login <= :authTo', ':authTo' => date('Y-m-d', $a_to)]; } } if (! empty($mass)) { $all = $this->input->post('all', TYPE_BOOL); $ids = $this->input->post('ids', TYPE_ARRAY_UINT); if (! $all) { $filter = ['user_id' => $ids]; } $count = $this->model->usersList($filter, [], true); $mass['sql'] = $filter; if ($count > 100) { $mass['count'] = $count; $this->app->cronManager()->executeOnce('users', 'cronAdminMassAction', $mass, md5(json_encode($mass))); $response = [ 'message' => _t('@users', 'The bulk operation is scheduled and will be completed within a few minutes.'), ]; } else { $response = $this->cronAdminMassAction($mass); } return $this->ajaxResponseForm($response); } $ordersAllowed = ['user_id' => 'desc', 'email' => 'asc', 'last_login' => 'desc']; $data = $this->prepareOrder($orderBy, $orderDirection, 'user_id' . tpl::ORDER_SEPARATOR . 'desc', $ordersAllowed); if (! $f['page']) { $f['page'] = 1; } $data['f'] = $f; $data['statusNotActivated'] = ($f['status'] == 2); $data['filter'] = '&' . http_build_query($f); $total = $this->model->usersList($filter, [], true); $pages = new Pagination($total, 15, $this->adminLink("listing{$data['filter']}&order=$orderBy-$orderDirection&page=" . Pagination::PAGE_ID)); $data['pgn'] = $pages->view(); $data['total'] = $total; $data['users'] = $this->model->usersList( $filter, [ 'user_id','admin','name','login','email','phone_number', 'company_id','last_login','blocked','activated','fake', ], false, $pages->getLimitOffset(), "$orderBy $orderDirection" ); # данные о компаниях пользователей if ($data['business_on'] = bff::businessEnabled()) { $aUsersCompanies = Business::model()->companiesDataToUsersListing((!empty($data['users']) ? array_keys($data['users']) : [])); foreach ($data['users'] as $k => &$v) { if (isset($aUsersCompanies[$k])) { $v['company'] = $aUsersCompanies[$k]; } } unset($v); } $data['list'] = $this->template('admin/listing.ajax', $data); if ($this->isAJAX()) { return $this->ajaxResponse([ 'list' => $data['list'], 'pgn' => $data['pgn'], 'total' => $data['total'], ]); } $data['massActions'] = $massActions; return $this->template('admin/listing', $data); } /** * Кеширование данных о пользователе * @param integer $userID * @return array */ public function userData($userID) { if (empty($userID)) { return []; } if (! isset($this->cache['user'][$userID])) { $this->cache['user'][$userID] = $this->model->userData($userID, '*'); } return $this->cache['user'][$userID]; } /** * Список модераторов * @return string */ public function listing_moderators() { if (! $this->haveAccessTo('admins-listing')) { return $this->showAccessDenied(); } $ordersAllowed = ['user_id' => 'desc', 'login' => 'asc', 'email' => 'asc']; $data = $this->prepareOrder($orderBy, $orderDirection, 'login' . tpl::ORDER_SEPARATOR . 'asc', $ordersAllowed); $filter = ['admin' => 1]; $total = $this->model->usersList($filter, [], true); $pages = new Pagination($total, 20, $this->adminLink(__FUNCTION__ . "&order=$orderBy-$orderDirection&page=" . Pagination::PAGE_ID)); $data['pgn'] = $pages->view(); $data['users'] = $this->model->usersList( $filter, ['user_id', 'login', 'email', 'password', 'blocked', 'deleted', 'activated'], false, $pages->getLimitOffset(), "$orderBy $orderDirection" ); # получаем все группы с доступом в админ-панель $usersGroups = $this->model->usersGroups(true, 'user_id'); foreach ($data['users'] as &$v) { $v['groups'] = $usersGroups[$v['user_id']] ?? []; } unset($v); $data['page'] = $pages->getCurrentPage(); return $this->template('admin/listing.moderators', $data); } /** * Форма добавления пользователя * @return string|mixed */ public function user_add() { if (! $this->haveAccessTo('users-edit')) { return $this->showAccessDenied(); } $data = []; $this->validateUserData($data, 0); if ($this->isPOST()) { $response = []; do { $data['password_salt'] = $this->security->generatePasswordSalt(); $data['password'] = $this->security->passwordHash($data['password'], $data['password_salt']); $data['activated'] = 1; if (! empty($data['email'])) { $data['email_verified'] = 1; } if (! empty($data['phone_number'])) { $data['phone_number_verified'] = 1; } $groupsID = $data['group_id']; unset($data['group_id']); if (!$this->errors->no('users.admin.user.submit', ['id' => 0, 'data' => &$data, 'groups' => &$groupsID])) { break; } $userID = $this->model->userCreate($data, $groupsID); if (! $userID) { $this->errors->impossible(); break; } $update = []; # upload avatar $avatar = $this->avatar($userID)->uploadFILES('avatar', false, false); if ($avatar !== false && !empty($avatar['filename'])) { $update['avatar'] = $avatar['filename']; } if (! empty($update)) { $this->model->userSave($userID, $update); } RegisteredEvent::dispatch($userID, ['createdByAdmin' => User::id()]); $response['redirect'] = ($this->model->userIsAdministrator($userID) ? 'listing_moderators' : 'listing' ); } while (false); return $this->iframeResponseForm($response); } $data = array_merge($data, ['password' => '', 'password2' => '', 'user_id' => '', 'avatar' => '']); $this->prepareGroupsOptions($data, [static::GROUPID_SUPERADMIN], [static::GROUPID_MEMBER]); $data['phones'] = []; # телефоны $data['user_id'] = 0; $data['business_on'] = bff::businessEnabled(); $data['region_title'] = ''; return $this->template('admin/user.form', $data); } /** * Форма редактирования пользователя * @return string|mixed */ public function user_edit() { if (! $this->haveAccessTo('users-edit')) { return $this->showAccessDenied(); } $userID = $this->input->get('rec', TYPE_UINT); if (! $userID) { return $this->adminRedirect(Errors::IMPOSSIBLE, 'listing'); } if ($this->model->userIsAdministrator($userID) && ! $this->haveAccessTo('admins-edit')) { return $this->showAccessDenied(); } $data = ['admin' => 0]; # анализируем группы, в которые входит пользователь $isSuperAdmin = 0; $userGroups = $this->model->userGroups($userID); foreach ($userGroups as $v) { if ($v['group_id'] == static::GROUPID_SUPERADMIN) { $isSuperAdmin = 1; } if ($v['adminpanel'] == 1) { $data['admin'] = 1; } } if ($this->isPOST()) { $response = ['reload' => false, 'back' => false]; $this->validateUserData($data, $userID); if (! $data['admin']) { # пропускаем настройки предназначенные только для администраторов unset($data['im_noreply']); } do { # основный данные $groupsID = $data['group_id'] ?? []; unset($data['group_id']); $data['member'] = in_array(static::GROUPID_MEMBER, $groupsID) ? 1 : 0; if (!$this->errors->no('users.admin.user.submit', ['id' => $userID,'data' => &$data,'groups' => &$groupsID])) { break; } $this->model->userSave($userID, $data); $update = []; # аватар $avatar = $this->avatar($userID)->uploadFILES('avatar', true, false); if ($avatar !== false && !empty($avatar['filename'])) { $update['avatar'] = $avatar['filename']; $response['reload'] = true; } else { if ($this->input->postget('avatar_del', TYPE_BOOL)) { if ($this->avatar($userID)->delete(false)) { $update['avatar'] = ''; $response['reload'] = true; } } } # связь с группами if ($isSuperAdmin && !in_array(static::GROUPID_SUPERADMIN, $groupsID)) { $groupsID = array_merge($groupsID, [static::GROUPID_SUPERADMIN]); } $this->model->userToGroups($userID, $groupsID); # обновляем, является ли юзер администратором if ($this->errors->no()) { $isAdmin = ($this->model->userIsAdministrator($userID) ? 1 : 0); if ($data['admin'] != $isAdmin) { $update['admin'] = $isAdmin; if (! $isAdmin) { $update['im_noreply'] = 0; } } } if (! empty($update)) { $this->model->userSave($userID, $update); } if ($this->input->post('back', TYPE_BOOL)) { $response['back'] = true; } } while (false); return $this->iframeResponseForm($response); } $userInfo = $this->model->userData($userID, '*', true); $data = HTML::escape(array_merge($userInfo, $data), 'html', ['name', 'site']); $activeGroupsID = []; for ($j = 0; $j < count($userGroups); $j++) { $activeGroupsID[] = $userGroups[$j]['group_id']; } $this->prepareGroupsOptions($data, ($isSuperAdmin ? null : static::GROUPID_SUPERADMIN), $activeGroupsID); # настройки компании $data['business_on'] = bff::businessEnabled(); $data['superadmin'] = $isSuperAdmin; $data['social'] = $this->social()->getUserSocialAccountsData($userID, true); $data['admin_auth'] = $this->adminAuthBlock(array_merge($data, $userInfo)); $data['permissionDelete'] = $this->haveAccessTo('users-delete'); if (! empty($data['fake'])) { $data['unfake_url'] = Admin::url('users/user_action', ['type' => 'unfake', 'rec' => $userID]); } return $this->template('admin/user.form', $data); } /** * Обработчик действий в форме редактирования пользователей * @return \bff\http\Response */ public function user_action() { if (! $this->haveAccessTo('users-edit')) { return $this->showAccessDenied(); } $userID = $this->input->getpost('rec', TYPE_UINT); if (! $userID) { return $this->adminRedirect(Errors::IMPOSSIBLE); } if ($this->model->userIsSuperAdmin($userID)) { return $this->adminRedirect(Errors::ACCESSDENIED); } if ($this->model->userIsAdministrator($userID) && ! $this->haveAccessTo('admins-edit')) { return $this->adminRedirect(Errors::ACCESSDENIED); } switch ($this->input->get('type')) { case 'delete': # удаление пользователя { # завершение сессии $this->userSessionDestroy($userID, false); # frontend if (! User::isCurrent($userID)) { $this->userSessionDestroy($userID, true); # admin panel } $saved = $this->model->userSave($userID, [ 'deleted' => static::DESTROY_BY_ADMIN, 'blocked' => 1, 'blocked_reason' => _t('@users', 'User account will be deleted within 24 hours'), ]); if ($saved) { $this->app->cronManager()->executeOnce('users', 'cronDeleteUsers'); } return $this->adminRedirect(Errors::SUCCESS); } case 'logout': # завершение сессии { $this->userSessionDestroy($userID, false); # frontend if (! User::isCurrent($userID)) { $this->userSessionDestroy($userID, true); # admin panel } return $this->adminRedirect(Errors::SUCCESS, "user_edit&rec=$userID"); } case 'unfake': # удаление флага fake { $this->userUnfake($userID); return $this->adminRedirect(Errors::SUCCESS, "user_edit&rec=$userID"); } } return $this->adminRedirect(Errors::SUCCESS); } /** * Обработчик ajax действий * @return \bff\http\Response */ public function ajax() { $userID = $this->input->getpost('id', TYPE_UINT); if (! $userID) { return $this->ajaxResponse(Errors::UNKNOWNRECORD); } $action = $this->input->getpost('act', TYPE_STR); switch ($action) { case 'user-info': # popup { if (! $this->haveAccessTo('members-listing')) { return $this->showAccessDenied(['popup' => true]); } $data = $this->model->userData($userID, '*'); $data['business_on'] = bff::businessEnabled(); if ($data['business_on'] && $data['company_id'] > 0) { $data['company'] = Business::model()->companyData($data['company_id'], ['title', 'link']); } $data['region_title'] = Geo::regionTitle($data['geo_city']); $data['im_form'] = $this->app->moduleExists('internalmail'); $data['social'] = $this->social()->getUserSocialAccountsData($userID, true); $data['admin_auth'] = $this->adminAuthBlock(array_merge($data, ['popup' => true])); return $this->adminModal($data, 'admin/user.info'); } case 'user-block': # блокировка / разблокировка пользователя { if (! $this->haveAccessTo('users-edit')) { return $this->ajaxResponse(Errors::ACCESSDENIED); } if (User::isCurrent($userID)) { return $this->ajaxResponse(Errors::IMPOSSIBLE); } $opt = [ 'blocked_reason' => $this->input->postget('blocked_reason', [TYPE_STR, 'len' => 1000]), 'blocked' => $this->input->postget('blocked', TYPE_BOOL), ]; if ($this->userBlock($userID, $opt)) { return $this->ajaxResponse([ 'reason' => nl2br($opt['blocked_reason']), 'blocked' => $opt['blocked'], ]); } } break; case 'user-activate': # активация пользователя { do { if (! $this->haveAccessTo('users-edit')) { $this->errors->accessDenied(); break; } $data = $this->model->userData($userID, ['user_id', 'activated', 'blocked']); if (empty($data)) { $this->errors->impossible(); break; } else { if ($data['activated'] == 1) { $this->errors->set(_t('@users', 'This account is already activated')); break; } else { if ($data['blocked'] == 1) { $this->errors->set(_t('@users', 'Unable to activate a suspended account')); break; } } } if (! $this->userActivate($userID, ['verifyPhone' => true])) { $this->errors->impossible(); } } while (false); return $this->ajaxResponseForm(); } case 'user-admin-comment': # комментарий о пользователе { $response = ['comment' => '']; do { if (! $this->haveAccessTo('users-edit')) { $this->errors->accessDenied(); break; } $data = $this->model->userData($userID, ['user_id', 'admin_comment']); if (empty($data)) { $this->errors->impossible(); break; } else { $response['comment'] = $this->input->post('admin_comment', [TYPE_TEXT, 'len' => 5000]); $this->model->userSave($userID, [ 'admin_comment' => $response['comment'], ]); } } while (false); $response['comment'] = nl2br($response['comment']); return $this->ajaxResponseForm($response); } case 'auth-url': { if (! $this->haveAccessTo('users-edit')) { return $this->showAccessDenied(); } if ($this->model->userIsAdministrator($userID)) { return $this->showAccessDenied(); } $userInfo = $this->model->userData($userID, '*', true); return $this->ajaxResponseForm([ 'url' => $this->adminAuthURL($userInfo['user_id'], $userInfo['last_login'], $userInfo['email']) ]); } default: { $this->app->hook('users.admin.ajax.default.action', $action, $this); } } return $this->ajaxResponse(Errors::IMPOSSIBLE); } /** * Формирование кнопки для авторизации на фронтенде * @param array $data * @return mixed|string */ public function adminAuthBlock($data = []) { if (! empty($data['admin'])) { return ''; } if (empty($data['user_id'])) { return ''; } $getData = false; foreach (['last_login', 'email'] as $f) { if (empty($data[$f])) { $getData = true; break; } } if ($getData) { $user = $this->model->userData($data['user_id'], ['user_id', 'last_login', 'email']); if (empty($user['user_id'])) { return ''; } $data = array_merge($user, $data); } $data['link'] = $this->adminAuthURL($data['user_id'], $data['last_login'], $data['email']); if (empty($data['link'])) { return ''; } return $this->template('admin/admin.auth', $data); } /** * Валидация пользователя * @param array $data @ref данные * @param int $userID ID пользователя * @return void */ protected function validateUserData(array &$data, $userID) { $params = [ 'name' => [TYPE_NOTAGS, 'len' => 50, 'len.sys' => 'users.contacts.name.limit'], 'firstname' => [TYPE_NOTAGS, 'len' => 50, 'len.sys' => 'users.contacts.firstname.limit'], 'surname' => [TYPE_NOTAGS, 'len' => 50, 'len.sys' => 'users.contacts.surname.limit'], 'email' => TYPE_NOTAGS, 'login' => TYPE_NOTAGS, 'geo_city' => TYPE_UINT, 'addr_addr' => [TYPE_NOTAGS, 'len' => 400, 'len.sys' => 'users.form.addr.limit'], 'company_id' => TYPE_UINT, # ID компании 'sex' => TYPE_UINT, 'contacts' => TYPE_ARRAY_NOTAGS, 'phones' => TYPE_ARRAY_NOTAGS, 'site' => TYPE_NOTAGS, 'about' => TYPE_NOTAGS, 'group_id' => TYPE_ARRAY_UINT, ]; $channels = Sendmail::channels(); if (! $this->registerPhone([static::REGISTER_TYPE_PHONE, static::REGISTER_TYPE_BOTH])) { unset($channels[Sendmail::CHANNEL_SMS]); } foreach ($channels as $k => $v) { $f = 'enotify' . ($k == Sendmail::CHANNEL_EMAIL ? '' : '_' . $k); $params[$f] = TYPE_ARRAY_UINT; } if ($userID) { $params['changepass'] = TYPE_BOOL; $params['password'] = TYPE_NOTRIM; $params['im_noreply'] = TYPE_BOOL; } else { $params['password'] = TYPE_NOTRIM; $params['password2'] = TYPE_NOTRIM; } if ($this->registerPhone([static::REGISTER_TYPE_PHONE, static::REGISTER_TYPE_BOTH])) { $params['phone_number'] = TYPE_NOTAGS; } if ($this->profileBirthdate) { $params['birthdate'] = TYPE_ARRAY_UINT; } $this->input->postm($params, $data); if (! $userID) { $data['admin'] = 0; } if ($this->isPOST()) { # номер телефона if ($this->registerPhone([static::REGISTER_TYPE_PHONE, static::REGISTER_TYPE_BOTH]) && (!empty($data['phone_number']) || !$userID)) { if (! $this->input->isPhoneNumber($data['phone_number'])) { $this->errors->set(_t('@users', 'Incorrect phone number'), 'phone_number'); } } if (! empty($data['phone_number'])) { if ($this->model->userPhoneExists($data['phone_number'], $userID)) { $this->errors->set(_t('@users', 'User with specified phone number was already registered'), 'phone_number'); } } # email (для авторизации) if ($this->registerPhone([static::REGISTER_TYPE_EMAIL, static::REGISTER_TYPE_BOTH]) && (!empty($data['email']) || !$userID)) { if (! $this->input->isEmail($data['email'])) { $this->errors->set(_t('@users', 'Incorrect email'), 'email'); } } if (! empty($data['email'])) { if ($this->model->userEmailExists($data['email'], $userID)) { $this->errors->set(_t('@users', 'Email already exists'), 'email'); } } # login if (! $this->isLoginCorrect($data['login'])) { $this->errors->set(_t('@users', 'Enter a correct login'), 'login'); } elseif ($this->model->userLoginExists($data['login'], $userID)) { $this->errors->set(_t('@users', 'Login already exists'), 'login'); } if ($userID) { if ($data['changepass']) { if (mb_strlen($data['password']) < $this->passwordMinLength) { $this->errors->set(_t('@users', 'New password is too short'), 'password'); } else { $dataCurrent = $this->model->userData($userID, ['password_salt']); $data['password'] = $this->security->passwordHash($data['password'], $dataCurrent['password_salt']); } } else { unset($data['password']); } unset($data['changepass']); } else { if (mb_strlen($data['password']) < $this->passwordMinLength) { $this->errors->set(_t('@users', 'Specified password is too short'), 'password'); } elseif ($data['password'] != $data['password2']) { $this->errors->set(_t('@users', 'Password confirmation failed'), 'password'); } unset($data['password2']); } # пол if (!in_array($data['sex'], [static::SEX_MALE, static::SEX_FEMALE])) { $data['sex'] = static::SEX_MALE; } $this->cleanUserData($data); } # уведомления foreach ($channels as $k => $v) { $f = 'enotify' . ($k == Sendmail::CHANNEL_EMAIL ? '' : '_' . $k); $data[$f] = array_sum($data[$f]); } } /** * Подготавливаем options для списков групп * @param array $data @ref * @param mixed $exceptGroup * @param array $activeGroupsID ID активных групп (в которых состоит пользователь) * @return void */ protected function prepareGroupsOptions(array &$data, $exceptGroup, $activeGroupsID = []) { $data['active_options'] = ''; $data['exists_options'] = ''; $groupsData = $this->model->groups($exceptGroup, false); $lang = $this->locale->current(); foreach ($groupsData as $v) { $option = ''; if (in_array($v['group_id'], $activeGroupsID)) { $data['active_options'] .= $option; } else { $data['exists_options'] .= $option; } } } }