/** * filter_dash_module_latest_log_activity * Sets theme variables and handles logic for the * dashboard's log history module. * @param string $module_id * @return string The contents of the module */ public function filter_dash_module_latest_log_activity( $module, $module_id, $theme ) { if ( false === ( $num_logs = Modules::get_option( $module_id, 'logs_number_display' ) ) ) { $num_logs = 8; } $params = array( 'where' => array( 'user_id' => User::identify()->id ), 'orderby' => 'id DESC', /* Otherwise, exactly same timestamp values muck it up... Plus, this is more efficient to sort on the primary key... */ 'limit' => $num_logs, ); $theme->logs = EventLog::get( $params ); // Create options form /* Commented out until fully implemented or it's decided to drop completely. See https://trac.habariproject.org/habari/ticket/1233 $form = new FormUI( 'dash_logs' ); $form->append( 'text', 'logs_number_display', 'option:' . Modules::storage_name( $module_id, 'logs_number_display' ), _t('Number of items') ); $form->append( 'submit', 'submit', _t('Submit') ); $form->properties['onsubmit'] = "dashboard.updateModule({$module_id}); return false;"; */ $module['title'] = ( User::identify()->can( 'manage_logs' ) ? '<a href="' . Site::get_url('admin') . '/logs">' . _t('Latest Log Activity') . '</a>' : _t('Latest Log Activity') ); //$module['options'] = $form->get(); $module['content'] = $theme->fetch( 'dash_logs' ); return $module; }
/** * Produce the content for the latest log activity block * @param Block $block The block object * @param Theme $theme The theme that the block will be output with */ public function action_block_content_latest_log_activity($block, $theme) { $params = array('where' => array('user_id' => User::identify()->id), 'orderby' => 'id DESC', 'limit' => isset($block->logs_number_display) ? $block->logs_number_display : 8); $block->logs = EventLog::get($params); $block->link = URL::get('admin', array('page' => 'logs')); $block->has_options = true; }
function action_auth_ajax_extendedlog($handler) { $log = EventLog::get(array('fetch_fn' => 'get_row', 'id' => $handler->handler_vars['log_id'], 'return_data' => true)); if (trim($log->data) == '') { $log->data = 'No additional data was logged.'; } echo $log->message . "<hr>\n"; echo $log->data; }
/** * filter_dash_module_latest_log_activity * Sets theme variables and handles logic for the * dashboard's log history module. * @param string $module_id * @return string The contents of the module */ public function filter_dash_module_latest_log_activity($module, $module_id, $theme) { if (FALSE === ($num_logs = Modules::get_option($module_id, 'logs_number_display'))) { $num_logs = 8; } $params = array('where' => array('user_id' => User::identify()->id), 'orderby' => 'id DESC', 'limit' => $num_logs); $theme->logs = EventLog::get($params); // Create options form $form = new FormUI('dash_logs'); $form->append('text', 'logs_number_display', 'option:' . Modules::storage_name($module_id, 'logs_number_display'), _t('Number of items')); $form->append('submit', 'submit', _t('Submit')); $form->properties['onsubmit'] = "dashboard.updateModule({$module_id}); return false;"; $module['title'] = User::identify()->can('manage_logs') ? '<a href="' . Site::get_url('admin') . '/logs">' . _t('Latest Log Activity') . '</a>' : _t('Latest Log Activity'); $module['options'] = $form->get(); $module['content'] = $theme->fetch('dash_logs'); return $module; }
/** * Assign values needed to display the logs page to the theme based on handlervars and parameters. * */ private function fetch_logs($params = NULL) { $locals = array('do_delete' => false, 'log_ids' => null, 'nonce' => '', 'timestamp' => '', 'PasswordDigest' => '', 'change' => '', 'limit' => 20, 'offset' => 0, 'user' => 0, 'date' => 'any', 'module' => '0', 'type' => '0', 'severity' => 'any', 'address' => '0', 'search' => '', 'do_search' => false, 'index' => 1); foreach ($locals as $varname => $default) { ${$varname} = isset($this->handler_vars[$varname]) ? $this->handler_vars[$varname] : $default; $this->theme->{$varname} = ${$varname}; } if ($do_delete && isset($log_ids)) { $okay = true; if (empty($nonce) || empty($timestamp) || empty($PasswordDigest)) { $okay = false; } $wsse = Utils::WSSE($nonce, $timestamp); if ($PasswordDigest != $wsse['digest']) { $okay = false; } if ($okay) { foreach ($log_ids as $id) { $ids[] = array('id' => $id); } $to_delete = EventLog::get(array('nolimit' => 1)); $count = 0; foreach ($to_delete as $log) { $log->delete(); $count++; } Session::notice(_t('Deleted %d logs', array($count))); } Utils::redirect(); } $this->theme->severities = LogEntry::list_severities(); $any = array('0' => 'Any'); $modulelist = LogEntry::list_logentry_types(); $modules = array(); $types = array(); $addresses = $any; $ips = DB::get_column('SELECT DISTINCT(ip) FROM {log}'); foreach ($ips as $ip) { $addresses[$ip] = long2ip($ip); } $this->theme->addresses = $addresses; foreach ($modulelist as $modulename => $typearray) { $modules['0,' . implode(',', $typearray)] = $modulename; foreach ($typearray as $typename => $typevalue) { if (!isset($types[$typename])) { $types[$typename] = '0'; } $types[$typename] .= ',' . $typevalue; } } $types = array_flip($types); $this->theme->types = array_merge($any, $types); $this->theme->modules = array_merge($any, $modules); // set up the users $users_temp = DB::get_results('SELECT DISTINCT username, user_id FROM {users} JOIN {log} ON {users}.id = {log}.user_id ORDER BY username ASC'); array_unshift($users_temp, new QueryRecord(array('username' => 'All', 'user_id' => 0))); foreach ($users_temp as $user_temp) { $users[$user_temp->user_id] = $user_temp->username; } $this->theme->users = $users; // set up dates. $dates = DB::get_column('SELECT timestamp FROM {log} ORDER BY timestamp DESC'); $dates = array_map(create_function('$date', 'return HabariDateTime::date_create( $date )->get(\'Y-m\');'), $dates); array_unshift($dates, 'Any'); $dates = array_combine($dates, $dates); $this->theme->dates = $dates; // prepare the WSSE tokens $this->theme->wsse = Utils::WSSE(); $arguments = array('severity' => LogEntry::severity($severity), 'limit' => $limit, 'offset' => $offset); // deduce type_id from module and type $r_type = explode(',', substr($type, 2)); $r_module = explode(',', substr($module, 2)); if ($type != '0' && $module != '0') { $arguments['type_id'] = array_intersect($r_type, $r_module); } elseif ($type == '0') { $arguments['type_id'] = $r_module; } elseif ($module == '0') { $arguments['type_id'] = $r_type; } if ('0' != $address) { $arguments['ip'] = $address; } if ('any' != strtolower($date)) { list($arguments['year'], $arguments['month']) = explode('-', $date); } if ('' != $search) { $arguments['criteria'] = $search; } if ('0' != $user) { $arguments['user_id'] = $user; } if (is_array($params)) { $arguments = array_merge($arguments, $params); } $this->theme->logs = EventLog::get($arguments); $monthcts = EventLog::get(array_merge($arguments, array('month_cts' => true))); foreach ($monthcts as $month) { if (isset($years[$month->year])) { $years[$month->year][] = $month; } else { $years[$month->year] = array($month); } } if (isset($years)) { $this->theme->years = $years; } else { $this->theme->years = array(); } }
/** * Handles spam deletion * * @return void **/ public function action_auth_ajax_deleteall($handler) { $result = array(); switch ($handler->handler_vars['target']) { case 'spam': if (!User::identify()->can('manage_all_comments')) { Session::error(_t('You do not have permission to do that action.')); break; } $total = Comments::count_total(Comment::STATUS_SPAM, FALSE); Comments::delete_by_status(Comment::status('spam')); Session::notice(sprintf(_t('Deleted all %s spam comments.'), $total)); break; case 'logs': if (!User::identify()->can('manage_logs')) { Session::error(_t('You do not have permission to do that action.')); break; } $to_delete = EventLog::get(array('date' => 'any', 'nolimit' => 1)); $count = 0; foreach ($to_delete as $log) { $log->delete(); $count++; } Session::notice(sprintf(_t('Deleted all %s log entries.'), $count)); break; } $result['messages'] = Session::messages_get(true, 'array'); echo json_encode($result); }
/** * Handles AJAX from /logs. * Used to delete logs. */ public function ajax_delete_logs($handler_vars) { Utils::check_request_method(array('POST')); $count = 0; $wsse = Utils::WSSE($handler_vars['nonce'], $handler_vars['timestamp']); if ($handler_vars['digest'] != $wsse['digest']) { Session::error(_t('WSSE authentication failed.')); echo Session::messages_get(true, array('Format', 'json_messages')); return; } foreach ($_POST as $id => $delete) { // skip POST elements which are not log ids if (preg_match('/^p\\d+$/', $id) && $delete) { $id = (int) substr($id, 1); $ids[] = array('id' => $id); } } if ((!isset($ids) || empty($ids)) && $handler_vars['action'] != 'purge') { Session::notice(_t('No logs selected.')); echo Session::messages_get(true, array('Format', 'json_messages')); return; } switch ($handler_vars['action']) { case 'delete': $to_delete = EventLog::get(array('date' => 'any', 'where' => $ids, 'nolimit' => 1)); foreach ($to_delete as $log) { $log->delete(); $count++; } Session::notice(_t('Deleted %d logs.', array($count))); break; case 'purge': $result = EventLog::purge(); Session::notice(_t('Logs purged.')); break; } echo Session::messages_get(true, array('Format', 'json_messages')); }
/** * Limit the number of log entries returned * - limit => the maximum number of posts to return, implicitly set for many queries * - nolimit => do not implicitly set limit */ public function test_get_logs_with_limit() { for ($i = 1; $i <= 5; $i++) { $entry = new LogEntry(array('user_id' => $this->user->id, 'type' => 'default', 'severity' => 'err', 'module' => 'habari', 'message' => 'Event message from test_logs_with_limit' . $i)); $entry->insert(); } $count_entries = EventLog::get(array('count' => 1, 'limit' => 2, 'user_id' => $this->user->id)); $this->assert_equal($count_entries, 5, "LIMIT with a COUNT is pointless - COUNTing anything should return a single value."); $entries = EventLog::get(array('limit' => 2, 'user_id' => $this->user->id)); $this->assert_equal(count($entries), 2); $count_entries = EventLog::get(array('count' => 1, 'nolimit' => 1, 'user_id' => $this->user->id)); $this->assert_true($count_entries > 2); $entries = EventLog::get(array('nolimit' => 1, 'user_id' => $this->user->id)); $this->assert_true(count($entries) > 2); // OFFSET based on page number (and limit) $entries = EventLog::get(array('limit' => 2, 'index' => 2, 'user_id' => $this->user->id)); $this->assert_equal(count($entries), 2); $entries = EventLog::get(array('limit' => 2, 'index' => 3, 'user_id' => $this->user->id)); $this->assert_equal(count($entries), 1); }
private function fetch_logs() { // load all the values for our filter drop-downs $dates = $this->fetch_log_dates(); $users = $this->fetch_log_users(); $ips = $this->fetch_log_ips(); extract($this->fetch_log_modules_types()); // $modules and $types $severities = LogEntry::list_severities(); // parse out the arguments we'll fetch logs for // the initial arguments $arguments = array('limit' => Controller::get_var('limit', 20), 'offset' => Controller::get_var('offset', 0)); // filter for the search field $search = Controller::get_var('search', ''); if ($search != '') { $arguments['criteria'] = $search; } // filter by date $date = Controller::get_var('date', 'any'); if ($date != 'any') { $d = DateTime::create($date); // ! means fill any non-specified pieces with default Unix Epoch ones $arguments['year'] = $d->format('Y'); $arguments['month'] = $d->format('m'); } // filter by user $user = Controller::get_var('user', 'any'); if ($user != 'any') { $arguments['user_id'] = $user; } // filter by ip $ip = Controller::get_var('address', 'any'); if ($ip != 'any') { $arguments['ip'] = $ip; } // filter modules and types // @todo get events of a specific type in a specific module, instead of either of the two // the interface doesn't currently make any link between module and type, so we won't worry about it for now $module = Controller::get_var('module', 'any'); $type = Controller::get_var('type', 'any'); if ($module != 'any') { // we get a slugified key back, get the actual module name $arguments['module'] = $modules[$module]; } if ($type != 'any') { // we get a slugified key back, get the actual type name $arguments['type'] = $types[$type]; } // filter by severity $severity = Controller::get_var('severity', 0); if ($severity != 0) { $arguments['severity'] = $severity; } // get the logs! $logs = EventLog::get($arguments); // last, but not least, generate the list of years used for the timeline $months = EventLog::get(array_merge($arguments, array('month_cts' => true))); $years = array(); foreach ($months as $m) { $years[$m->year][] = $m; } // assign all our theme values in one spot // first the filter options $this->theme->dates = $dates; $this->theme->users = $users; $this->theme->addresses = $ips; $this->theme->modules = $modules; $this->theme->types = $types; $this->theme->severities = $severities; // next the filter criteria we used $this->theme->search_args = $search; $this->theme->date = $date; $this->theme->user = $user; $this->theme->address = $ip; $this->theme->module = $module; $this->theme->type = $type; $this->theme->severity = $severity; $this->theme->logs = $logs; $this->theme->years = $years; $form = new FormUI('logs_batch', 'logs_batch'); $form->append(FormControlAggregate::create('entries')->set_selector('.log_entry')->set_value(array())->label('None Selected')); $form->append($actions = FormControlDropbutton::create('actions')); $actions->append(FormControlSubmit::create('delete_selected')->on_success(function (FormUI $form) { $ids = $form->entries->value; $count = 0; /** @var LogEntry $log */ foreach ($ids as $id) { $logs = EventLog::get(array('id' => $id)); foreach ($logs as $log) { $log->delete(); $count++; } } Session::notice(_t('Deleted %d logs.', array($count))); $form->bounce(false); })->set_caption(_t('Delete Selected'))); $actions->append(FormControlSubmit::create('purge_logs')->on_success(function (FormUI $form) { if (EventLog::purge()) { Session::notice(_t('Logs purged.')); } else { Session::notice(_t('There was a problem purging the event logs.')); } $form->bounce(false); })->set_caption(_t('Purge Logs'))); $this->theme->form = $form; $this->theme->wsse = Utils::WSSE(); // prepare a WSSE token for any ajax calls }
/** * Return a single requested log entry. * * <code> * $log= LogEntry::get( array( 'id' => 5 ) ); * </code> * * @param array $paramarray An associated array of parameters, or a querystring * @return object LogEntry The first log entry that matched the given criteria */ public static function get( $paramarray = array() ) { // Default parameters. $defaults = array ( 'fetch_fn' => 'get_row', ); $user = User::identify(); if ( $user->loggedin ) { $defaults['where'][] = array( 'user_id' => $user->id, ); } foreach ( $defaults['where'] as $index => $where ) { $defaults['where'][$index] = array_merge( $where, Utils::get_params( $paramarray ) ); } // Make sure we fetch only a single event. (LIMIT 1) $defaults['limit'] = 1; return EventLog::get( $defaults ); }
private function fetch_logs () { // load all the values for our filter drop-downs $dates = $this->fetch_log_dates(); $users = $this->fetch_log_users(); $ips = $this->fetch_log_ips(); extract( $this->fetch_log_modules_types() ); // $modules and $types $severities = LogEntry::list_severities(); // parse out the arguments we'll fetch logs for // the initial arguments $arguments = array( 'limit' => Controller::get_var( 'limit', 20 ), 'offset' => Controller::get_var( 'offset', 0 ), ); // filter for the search field $search = Controller::get_var( 'search', '' ); if ( $search != '' ) { $arguments['criteria'] = $search; } // filter by date $date = Controller::get_var( 'date', 'any' ); if ( $date != 'any' ) { $d = DateTime::createFromFormat( '!Y-m', $date ); // ! means fill any non-specified pieces with default Unix Epoch ones $arguments['year'] = $d->format( 'Y' ); $arguments['month'] = $d->format( 'm' ); } // filter by user $user = Controller::get_var( 'user', 'any' ); if ( $user != 'any' ) { $arguments['user_id'] = $user; } // filter by ip $ip = Controller::get_var( 'address', 'any' ); if ( $ip != 'any' ) { $arguments['ip'] = $ip; } // filter modules and types // @todo get events of a specific type in a specific module, instead of either of the two // the interface doesn't currently make any link between module and type, so we won't worry about it for now $module = Controller::get_var( 'module', 'any' ); $type = Controller::get_var( 'type', 'any' ); if ( $module != 'any' ) { // we get a slugified key back, get the actual module name $arguments['module'] = $modules[ $module ]; } if ( $type != 'any' ) { // we get a slugified key back, get the actual type name $arguments['type'] = $types[ $type ]; } // filter by severity $severity = Controller::get_var( 'severity', 'any' ); if ( $severity != 'any' ) { $arguments['severity'] = $severity; } // get the logs! $logs = EventLog::get( $arguments ); // last, but not least, generate the list of years used for the timeline $months = EventLog::get( array_merge( $arguments, array( 'month_cts' => true ) ) ); $years = array(); foreach ( $months as $m ) { $years[ $m->year ][] = $m; } // assign all our theme values in one spot // first the filter options $this->theme->dates = $dates; $this->theme->users = $users; $this->theme->addresses = $ips; $this->theme->modules = $modules; $this->theme->types = $types; $this->theme->severities = $severities; // next the filter criteria we used $this->theme->search = $search; $this->theme->date = $date; $this->theme->user = $user; $this->theme->address = $ip; $this->theme->module = $module; $this->theme->type = $type; $this->theme->severity = $severity; $this->theme->logs = $logs; $this->theme->years = $years; $this->theme->wsse = Utils::WSSE(); // prepare a WSSE token for any ajax calls }