diff --git a/src/psm/Module/Server/Controller/AbstractServerController.class.php b/src/psm/Module/Server/Controller/AbstractServerController.class.php new file mode 100644 index 00000000..5e33f90b --- /dev/null +++ b/src/psm/Module/Server/Controller/AbstractServerController.class.php @@ -0,0 +1,127 @@ +. + * + * @package phpservermon + * @author Pepijn Over + * @copyright Copyright (c) 2008-2014 Pepijn Over + * @license http://www.gnu.org/licenses/gpl.txt GNU GPL v3 + * @version Release: v3.1.1 + * @link http://www.phpservermonitor.org/ + * @since phpservermon 3.0.0 + **/ + +namespace psm\Module\Server\Controller; +use psm\Module\AbstractController; +use psm\Service\Database; + +abstract class AbstractServerController extends AbstractController { + + function __construct(Database $db, \Twig_Environment $twig) { + parent::__construct($db, $twig); + } + + /** + * Get all servers for the current user + * @param int $server_id if true only that server will be retrieved. + * @return array + */ + public function getServers($server_id = null) { + $sql_join = ''; + $sql_where = ''; + + if($this->user != null && $this->user->getUserLevel() > PSM_USER_ADMIN) { + // restrict by user_id + $sql_join = "JOIN `".PSM_DB_PREFIX."users_servers` AS `us` ON ( + `us`.`user_id`={$this->user->getUserId()} + AND `us`.`server_id`=`s`.`server_id` + )"; + } + if($server_id !== null) { + $server_id = intval($server_id); + $sql_where ="WHERE `s`.`server_id`={$server_id} "; + } + + $sql = "SELECT + `s`.`server_id`, + `s`.`ip`, + `s`.`port`, + `s`.`type`, + `s`.`label`, + `s`.`pattern`, + `s`.`status`, + `s`.`error`, + `s`.`rtime`, + `s`.`last_check`, + `s`.`last_online`, + `s`.`active`, + `s`.`email`, + `s`.`sms`, + `s`.`pushover`, + `s`.`pushsafer`, + `s`.`warning_threshold`, + `s`.`warning_threshold_counter`, + `s`.`timeout` + FROM `".PSM_DB_PREFIX."servers` AS `s` + {$sql_join} + {$sql_where} + ORDER BY `active` ASC, `status` DESC, `label` ASC"; + $servers = $this->db->query($sql); + + if($server_id !== null && count($servers) == 1) { + $servers = $servers[0]; + } + + return $servers; + } + + /** + * Format server data for display + * @param array $server + * @return array + */ + protected function formatServer($server) { + $server['rtime'] = round((float) $server['rtime'], 4); + $server['last_online'] = psm_timespan($server['last_online']); + $server['last_check'] = psm_timespan($server['last_check']); + $server['active'] = psm_get_lang('system', $server['active']); + $server['email'] = psm_get_lang('system', $server['email']); + $server['sms'] = psm_get_lang('system', $server['sms']); + $server['pushover'] = psm_get_lang('system', $server['pushover']); + $server['pushsafer'] = psm_get_lang('system', $server['pushsafer']); + + if($server['status'] == 'on' && $server['warning_threshold_counter'] > 0) { + $server['status'] = 'warning'; + } + + $server['error'] = htmlentities($server['error']); + $server['type'] = psm_get_lang('servers', 'type_' . $server['type']); + $server['timeout'] = ($server['timeout'] > 0) ? $server['timeout'] : PSM_CURL_TIMEOUT; + + $url_actions = array('delete', 'edit', 'view'); + foreach($url_actions as $action) { + $server['url_' . $action] = psm_build_url(array( + 'mod' => 'server', + 'action' => $action, + 'id' => $server['server_id'], + )); + } + + return $server; + } +} diff --git a/src/psm/Module/Server/Controller/LogController.class.php b/src/psm/Module/Server/Controller/LogController.class.php new file mode 100644 index 00000000..80d922a9 --- /dev/null +++ b/src/psm/Module/Server/Controller/LogController.class.php @@ -0,0 +1,152 @@ +. + * + * @package phpservermon + * @author Pepijn Over + * @copyright Copyright (c) 2008-2014 Pepijn Over + * @license http://www.gnu.org/licenses/gpl.txt GNU GPL v3 + * @version Release: v3.1.1 + * @link http://www.phpservermonitor.org/ + **/ + +namespace psm\Module\Server\Controller; +use psm\Service\Database; + +/** + * Log module. Create the page to view previous log messages + */ +class LogController extends AbstractServerController { + + function __construct(Database $db, \Twig_Environment $twig) { + parent::__construct($db, $twig); + + $this->setActions('index', 'index'); + } + + /** + * Prepare the template with a list of all log entries + */ + protected function executeIndex() { + $this->twig->addGlobal('subtitle', psm_get_lang('menu', 'server_log')); + $tpl_data = array( + 'label_status' => psm_get_lang('log', 'status'), + 'label_email' => psm_get_lang('log', 'email'), + 'label_sms' => psm_get_lang('log', 'sms'), + 'label_pushover' => psm_get_lang('log', 'pushover'), + 'label_pushsafer' => psm_get_lang('log', 'pushsafer'), + 'label_title' => psm_get_lang('log', 'title'), + 'label_server' => psm_get_lang('servers', 'server'), + 'label_type' => psm_get_lang('log', 'type'), + 'label_message' => psm_get_lang('system', 'message'), + 'label_date' => psm_get_lang('system', 'date'), + 'label_users' => ucfirst(psm_get_lang('menu', 'user')), + 'label_no_logs' => psm_get_lang('log', 'no_logs'), + 'tabs' => array(), + ); + $log_types = array('status', 'email', 'sms', 'pushover', 'pushsafer'); + + // get users + $users = $this->db->select(PSM_DB_PREFIX.'users', null, array('user_id','name')); + + $users_labels = array(); + foreach ($users as $user) { + $users_labels[$user['user_id']] = $user['name']; + } + + foreach($log_types as $key) { + $records = $this->getEntries($key); + $log_count = count($records); + + $tab_data = array( + 'id' => $key, + 'has_users' => ($key == 'status') ? false : true, + 'no_logs' => ($log_count == 0) ? true : false, + 'tab_active' => ($key == 'status') ? 'active' : '', + ); + + for ($x = 0; $x < $log_count; $x++) { + $record = &$records[$x]; + $record['class'] = ($x & 1) ? 'odd' : 'even'; + $record['users'] = ''; + $record['server'] = $record['label']; + $record['type_icon'] = ($record['server_type'] == 'website') ? 'icon-globe' : 'icon-cog'; + $record['type_title'] = psm_get_lang('servers', 'type_' . $record['server_type']); + $ip = '(' . $record['ip']; + if(!empty($record['port']) && (($record['server_type'] != 'website') || ($record['port'] != 80))) { + $ip .= ':' . $record['port']; + } + $ip .= ')'; + $record['ip'] = $ip; + $record['datetime_format'] = psm_date($record['datetime']); + + // fix up user list + if(!empty($record['user_id'])) { + $names = array(); + $users = explode(',', $record['user_id']); + foreach($users as $user_id) { + if(isset($users_labels[$user_id])) { + $names[] = $users_labels[$user_id]; + } + } + sort($names); + $record['users'] = implode('
', $names); + $record['user_list'] = implode(' • ', $names); + } + } + $tab_data['entries'] = $records; + $tpl_data['tabs'][] = $tab_data; + } + return $this->twig->render('module/server/log.tpl.html', $tpl_data); + } + + /** + * Get all the log entries for a specific $type + * + * @param string $type status/email/sms + * @return array + */ + public function getEntries($type) { + $sql_join = ''; + if($this->user != null && $this->user->getUserLevel() > PSM_USER_ADMIN) { + // restrict by user_id + $sql_join = "JOIN `".PSM_DB_PREFIX."users_servers` AS `us` ON ( + `us`.`user_id`={$this->user->getUserId()} + AND `us`.`server_id`=`servers`.`server_id` + )"; + } + $entries = $this->db->query( + 'SELECT '. + '`servers`.`label`, '. + '`servers`.`ip`, '. + '`servers`.`port`, '. + '`servers`.`type` AS server_type, '. + '`log`.`type`, '. + '`log`.`message`, '. + '`log`.`datetime`, '. + '`log`.`user_id` '. + 'FROM `'.PSM_DB_PREFIX.'log` AS `log` '. + 'JOIN `'.PSM_DB_PREFIX.'servers` AS `servers` ON (`servers`.`server_id`=`log`.`server_id`) '. + $sql_join . + 'WHERE `log`.`type`=\''.$type.'\' '. + 'ORDER BY `datetime` DESC '. + 'LIMIT 0,20' + ); + return $entries; + } +} diff --git a/src/psm/Module/Server/Controller/ServerController.class.php b/src/psm/Module/Server/Controller/ServerController.class.php new file mode 100644 index 00000000..d161ba95 --- /dev/null +++ b/src/psm/Module/Server/Controller/ServerController.class.php @@ -0,0 +1,443 @@ +. + * + * @package phpservermon + * @author Pepijn Over + * @copyright Copyright (c) 2008-2014 Pepijn Over + * @license http://www.gnu.org/licenses/gpl.txt GNU GPL v3 + * @version Release: v3.1.1 + * @link http://www.phpservermonitor.org/ + **/ + +namespace psm\Module\Server\Controller; +use psm\Service\Database; + +/** + * Server module. Add/edit/delete servers, show a list of all servers etc. + */ +class ServerController extends AbstractServerController { + + /** + * Current server id + * @var int $server_id + */ + protected $server_id; + + function __construct(Database $db, \Twig_Environment $twig) { + parent::__construct($db, $twig); + + $this->server_id = isset($_GET['id']) ? intval($_GET['id']) : 0; + + $this->setActions(array( + 'index', 'edit', 'save', 'delete', 'view', + ), 'index'); + + // make sure only admins are allowed to edit/delete servers: + $this->setMinUserLevelRequiredForAction(PSM_USER_ADMIN, array( + 'delete', 'edit', 'save' + )); + $this->twig->addGlobal('subtitle', psm_get_lang('menu', 'server')); + } + + /** + * Prepare the template to show a list of all servers + */ + protected function executeIndex() { + $tpl_data = $this->getLabels(); + $tpl_data['user_level'] = $this->user->getUserLevel(); + $sidebar = new \psm\Util\Module\Sidebar($this->twig); + $this->setSidebar($sidebar); + + // check if user is admin, in that case we add the buttons + if($this->user->getUserLevel() == PSM_USER_ADMIN) { + $modal = new \psm\Util\Module\Modal($this->twig, 'delete', \psm\Util\Module\Modal::MODAL_TYPE_DANGER); + $this->addModal($modal); + $modal->setTitle(psm_get_lang('servers', 'delete_title')); + $modal->setMessage(psm_get_lang('servers', 'delete_message')); + $modal->setOKButtonLabel(psm_get_lang('system', 'delete')); + + $sidebar->addButton( + 'add_new', + psm_get_lang('system', 'add_new'), + psm_build_url(array('mod' => 'server', 'action' => 'edit')), + 'plus icon-white', 'success' + ); + } + + $sidebar->addButton( + 'update', + psm_get_lang('menu', 'server_update'), + psm_build_url(array('mod' => 'server_update')), + 'refresh' + ); + + $icons = array( + 'email' => 'icon-envelope', + 'sms' => 'icon-mobile', + 'pushover' => 'icon-pushover', + 'pushsafer' => 'icon-pushsafer', + ); + + $servers = $this->getServers(); + $server_count = count($servers); + + for ($x = 0; $x < $server_count; $x++) { + $servers[$x]['class'] = ($x & 1) ? 'odd' : 'even'; + + if($servers[$x]['type'] == 'website') { + $servers[$x]['type_icon'] = 'icon-globe'; + // add link to label + $ip = $servers[$x]['ip']; + if(!empty($servers[$x]['port']) && ($servers[$x]['port'] != 80)) { + $ip .= ' : ' . $servers[$x]['port']; + } + $servers[$x]['ip'] = ''.$ip.''; + $servers[$x]['ip_short'] = $ip; + } else { + $servers[$x]['type_icon'] = 'icon-cog'; + $servers[$x]['ip_short'] = $servers[$x]['ip'] . ' : ' . $servers[$x]['port']; + } + if(($servers[$x]['active'] == 'yes')) { + $servers[$x]['active_icon'] = 'icon-eye-open'; + $servers[$x]['active_title'] = psm_get_lang('servers', 'monitoring'); + + foreach($icons as $i_id => $i_icon) { + if(psm_get_conf($i_id . '_status') && $servers[$x][$i_id] == 'yes') { + $servers[$x][$i_id . '_icon'] = $i_icon; + } + } + } else { + $servers[$x]['active_icon'] = 'icon-eye-close'; + $servers[$x]['active_title'] = psm_get_lang('servers', 'no_monitoring'); + } + + $servers[$x] = $this->formatServer($servers[$x]); + } + $tpl_data['servers'] = $servers; + return $this->twig->render('module/server/server/list.tpl.html', $tpl_data); + } + + /** + * Prepare the template to show the update screen for a single server + */ + protected function executeEdit() { + $back_to = isset($_GET['back_to']) ? $_GET['back_to'] : ''; + + $tpl_data = $this->getLabels(); + $tpl_data['edit_server_id'] = $this->server_id; + $tpl_data['url_save'] = psm_build_url(array( + 'mod' => 'server', + 'action' => 'save', + 'id' => $this->server_id, + 'back_to' => $back_to, + )); + + // depending on where the user came from, add the go back url: + if($back_to == 'view' && $this->server_id > 0) { + $tpl_data['url_go_back'] = psm_build_url(array('mod' => 'server', 'action' => 'view', 'id' => $this->server_id)); + } else { + $tpl_data['url_go_back'] = psm_build_url(array('mod' => 'server')); + } + + $tpl_data['users'] = $this->db->select(PSM_DB_PREFIX.'users', null, array('user_id', 'name'), '', 'name'); + + switch($this->server_id) { + case 0: + // insert mode + $tpl_data['titlemode'] = psm_get_lang('system', 'insert'); + $tpl_data['edit_value_warning_threshold'] = '1'; + + $edit_server = $_POST; + break; + default: + // edit mode + // get server entry + $edit_server = $this->getServers($this->server_id); + if(empty($edit_server)) { + $this->addMessage(psm_get_lang('servers', 'error_server_no_match'), 'error'); + return $this->initializeAction('index'); + } + $tpl_data['titlemode'] = psm_get_lang('system', 'edit') . ' ' . $edit_server['label']; + + $user_idc_selected = $this->getServerUsers($this->server_id); + foreach($tpl_data['users'] as &$user) { + if(in_array($user['user_id'], $user_idc_selected)) { + $user['edit_selected'] = 'selected="selected"'; + } + } + + break; + } + + if(!empty($edit_server)) { + // attempt to prefill previously posted fields + foreach($edit_server as $key => $value) { + $edit_server[$key] = psm_POST($key, $value); + } + + $tpl_data = array_merge($tpl_data, array( + 'edit_value_label' => $edit_server['label'], + 'edit_value_ip' => $edit_server['ip'], + 'edit_value_port' => $edit_server['port'], + 'edit_value_timeout' => $edit_server['timeout'], + 'default_value_timeout' => PSM_CURL_TIMEOUT, + 'edit_value_pattern' => $edit_server['pattern'], + 'edit_value_warning_threshold' => $edit_server['warning_threshold'], + 'edit_type_selected_' . $edit_server['type'] => 'selected="selected"', + 'edit_active_selected_' . $edit_server['active'] => 'selected="selected"', + 'edit_email_selected_' . $edit_server['email'] => 'selected="selected"', + 'edit_sms_selected_' . $edit_server['sms'] => 'selected="selected"', + 'edit_pushover_selected_' . $edit_server['pushover'] => 'selected="selected"', + 'edit_pushsafer_selected_' . $edit_server['pushsafer'] => 'selected="selected"', + )); + } + + $notifications = array('email', 'sms', 'pushover', 'pushsafer'); + foreach($notifications as $notification) { + if(psm_get_conf($notification . '_status') == 0) { + $tpl_data['warning_' . $notification] = true; + $tpl_data['control_class_' . $notification] = 'warning'; + $tpl_data['label_warning_' . $notification] = psm_get_lang( + 'servers', 'warning_notifications_disabled_' . $notification + ); + } else { + $tpl_data['warning_' . $notification] = false; + } + } + + return $this->twig->render('module/server/server/update.tpl.html', $tpl_data); + } + + /** + * Executes the saving of one of the servers + */ + protected function executeSave() { + if(empty($_POST)) { + // dont process anything if no data has been posted + return $this->executeIndex(); + } + $clean = array( + 'label' => trim(strip_tags(psm_POST('label', ''))), + 'ip' => trim(strip_tags(psm_POST('ip', ''))), + 'timeout' => (isset($_POST['timeout']) && intval($_POST['timeout']) > 0) ? intval($_POST['timeout']) : null, + 'port' => intval(psm_POST('port', 0)), + 'type' => psm_POST('type', ''), + 'pattern' => psm_POST('pattern', ''), + 'warning_threshold' => intval(psm_POST('warning_threshold', 0)), + 'active' => in_array($_POST['active'], array('yes', 'no')) ? $_POST['active'] : 'no', + 'email' => in_array($_POST['email'], array('yes', 'no')) ? $_POST['email'] : 'no', + 'sms' => in_array($_POST['sms'], array('yes', 'no')) ? $_POST['sms'] : 'no', + 'pushover' => in_array($_POST['pushover'], array('yes', 'no')) ? $_POST['pushover'] : 'no', + 'pushsafer' => in_array($_POST['pushsafer'], array('yes', 'no')) ? $_POST['pushsafer'] : 'no', + ); + // make sure websites start with http:// + if($clean['type'] == 'website' && substr($clean['ip'], 0, 4) != 'http') { + $clean['ip'] = 'http://' . $clean['ip']; + } + + // validate the lot + $server_validator = new \psm\Util\Server\ServerValidator($this->db); + + try { + if($this->server_id > 0) { + $server_validator->serverId($this->server_id); + } + $server_validator->label($clean['label']); + $server_validator->type($clean['type']); + $server_validator->ip($clean['ip'], $clean['type']); + $server_validator->warningThreshold($clean['warning_threshold']); + } catch(\InvalidArgumentException $ex) { + $this->addMessage(psm_get_lang('servers', 'error_' . $ex->getMessage()), 'error'); + return $this->executeEdit(); + } + + // check for edit or add + if($this->server_id > 0) { + // edit + $this->db->save( + PSM_DB_PREFIX.'servers', + $clean, + array('server_id' => $this->server_id) + ); + $this->addMessage(psm_get_lang('servers', 'updated'), 'success'); + } else { + // add + $clean['status'] = 'on'; + $this->server_id = $this->db->save(PSM_DB_PREFIX.'servers', $clean); + $this->addMessage(psm_get_lang('servers', 'inserted'), 'success'); + } + + // update users + $user_idc = psm_POST('user_id', array()); + $user_idc_save = array(); + + foreach($user_idc as $user_id) { + $user_idc_save[] = array( + 'user_id' => intval($user_id), + 'server_id' => intval($this->server_id), + ); + } + $this->db->delete(PSM_DB_PREFIX.'users_servers', array('server_id' => $this->server_id)); + if(!empty($user_idc_save)) { + // add all new users + $this->db->insertMultiple(PSM_DB_PREFIX.'users_servers', $user_idc_save); + } + + $back_to = isset($_GET['back_to']) ? $_GET['back_to'] : 'index'; + if($back_to == 'view') { + return $this->initializeAction('view'); + } else { + return $this->initializeAction('index'); + } + } + + /** + * Executes the deletion of one of the servers + */ + protected function executeDelete() { + if(isset($_GET['id'])) { + $id = intval($_GET['id']); + // do delete + $res = $this->db->delete(PSM_DB_PREFIX . 'servers', array('server_id' => $id)); + + if($res === 1) { + $this->db->delete(PSM_DB_PREFIX.'log', array('server_id' => $id)); + $this->db->delete(PSM_DB_PREFIX.'users_servers', array('server_id' => $id)); + $this->db->delete(PSM_DB_PREFIX.'servers_uptime', array('server_id' => $id)); + $this->db->delete(PSM_DB_PREFIX.'servers_history', array('server_id' => $id)); + } + $this->addMessage(psm_get_lang('servers', 'deleted'), 'success'); + } + return $this->initializeAction('index'); + } + + /** + * Prepare the view template + */ + protected function executeView() { + if($this->server_id == 0) { + return $this->initializeAction('index'); + } + $server = $this->getServers($this->server_id); + + if(empty($server)) { + return $this->initializeAction('index'); + } + + $tpl_data = $this->getLabels(); + $tpl_data = array_merge($tpl_data, $this->formatServer($server)); + + // create history HTML + $history = new \psm\Util\Server\HistoryGraph($this->db, $this->twig); + $tpl_data['html_history'] = $history->createHTML($this->server_id); + + // add edit/delete buttons for admins + if($this->user->getUserLevel() == PSM_USER_ADMIN) { + $tpl_data['has_admin_actions'] = true; + $tpl_data['url_edit'] = psm_build_url(array('mod' => 'server', 'action' => 'edit', 'id' => $this->server_id, 'back_to' => 'view')); + + $modal = new \psm\Util\Module\Modal($this->twig, 'delete', \psm\Util\Module\Modal::MODAL_TYPE_DANGER); + $this->addModal($modal); + $modal->setTitle(psm_get_lang('servers', 'delete_title')); + $modal->setMessage(psm_get_lang('servers', 'delete_message')); + $modal->setOKButtonLabel(psm_get_lang('system', 'delete')); + } + + // add all available servers to the menu + $servers = $this->getServers(); + $tpl_data['options'] = array(); + foreach($servers as $i => $server_available) { + $tpl_data['options'][] = array( + 'class_active' => ($server_available['server_id'] == $this->server_id) ? 'active' : '', + 'url' => psm_build_url(array('mod' => 'server', 'action' => 'view', 'id' => $server_available['server_id'])), + 'label' => $server_available['label'], + ); + } + + $sidebar = new \psm\Util\Module\Sidebar($this->twig); + $this->setSidebar($sidebar); + + // check which module the user came from, and add a link accordingly + $back_to = isset($_GET['back_to']) && $_GET['back_to'] == 'server_status' ? $_GET['back_to'] : 'server'; + $sidebar->addButton( + 'go_back', + psm_get_lang('system', 'go_back'), + psm_build_url(array('mod' => $back_to)), + 'th-list' + ); + + return $this->twig->render('module/server/server/view.tpl.html', $tpl_data); + } + + protected function getLabels() { + return array( + 'label_label' => psm_get_lang('servers', 'label'), + 'label_status' => psm_get_lang('servers', 'status'), + 'label_domain' => psm_get_lang('servers', 'domain'), + 'label_timeout' => psm_get_lang('servers', 'timeout'), + 'label_timeout_description' => psm_get_lang('servers', 'timeout_description'), + 'label_port' => psm_get_lang('servers', 'port'), + 'label_type' => psm_get_lang('servers', 'type'), + 'label_website' => psm_get_lang('servers', 'type_website'), + 'label_service' => psm_get_lang('servers', 'type_service'), + 'label_type' => psm_get_lang('servers', 'type'), + 'label_pattern' => psm_get_lang('servers', 'pattern'), + 'label_pattern_description' => psm_get_lang('servers', 'pattern_description'), + 'label_last_check' => psm_get_lang('servers', 'last_check'), + 'label_rtime' => psm_get_lang('servers', 'latency'), + 'label_last_online' => psm_get_lang('servers', 'last_online'), + 'label_monitoring' => psm_get_lang('servers', 'monitoring'), + 'label_email' => psm_get_lang('servers', 'email'), + 'label_send_email' => psm_get_lang('servers', 'send_email'), + 'label_sms' => psm_get_lang('servers', 'sms'), + 'label_send_sms' => psm_get_lang('servers', 'send_sms'), + 'label_pushover' => psm_get_lang('servers', 'pushover'), + 'label_pushsafer' => psm_get_lang('servers', 'pushsafer'), + 'label_users' => psm_get_lang('servers', 'users'), + 'label_warning_threshold' => psm_get_lang('servers', 'warning_threshold'), + 'label_warning_threshold_description' => psm_get_lang('servers', 'warning_threshold_description'), + 'label_action' => psm_get_lang('system', 'action'), + 'label_save' => psm_get_lang('system', 'save'), + 'label_go_back' => psm_get_lang('system', 'go_back'), + 'label_edit' => psm_get_lang('system', 'edit'), + 'label_delete' => psm_get_lang('system', 'delete'), + 'label_yes' => psm_get_lang('system', 'yes'), + 'label_no' => psm_get_lang('system', 'no'), + 'label_add_new' => psm_get_lang('system', 'add_new'), + ); + } + + /** + * Get all user ids for a server + * @param int $server_id + * @return array with ids only + */ + protected function getServerUsers($server_id) { + $users = $this->db->select( + PSM_DB_PREFIX.'users_servers', + array('server_id' => $server_id), + array('user_id') + ); + $result = array(); + foreach($users as $user) { + $result[] = $user['user_id']; + } + return $result; + } +}