Merge branch 'maint/7.0'
[ninja.git] / application / controllers / ajax.php
blob1110fd56c55f18acf56c4229ab4ca18e3bf2a69e
1 <?php defined('SYSPATH') OR die('No direct access allowed.');
2 /**
3 * Controller to fetch data via Ajax calls
4 * Requires authentication
6 * op5, and the op5 logo are trademarks, servicemarks, registered servicemarks
7 * or registered trademarks of op5 AB.
8 * All other trademarks, servicemarks, registered trademarks, and registered
9 * servicemarks mentioned herein may be the property of their respective owner(s).
10 * The information contained herein is provided AS IS with NO WARRANTY OF ANY
11 * KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY, AND FITNESS FOR A
12 * PARTICULAR PURPOSE.
15 class Ajax_Controller extends Authenticated_Controller {
17 public function __construct()
19 parent::__construct();
21 /* Ajax calls shouldn't be rendered. This doesn't, because some unknown
22 * magic doesn't render templates in ajax requests, but for debugging
24 $this->auto_render = false;
27 public function command ( $method = false, $command = false ) {
29 $method = $this->input->post( 'method', $method );
30 $command = $this->input->post( 'command', $command );
31 $naming = preg_replace( "/^(STOP|START|ENABLE|DISABLE)\_/", "", $command );
33 $cmd_name_mapping = array(
34 "NOTIFICATIONS" => "enable_notifications",
35 'EXECUTING_SVC_CHECKS' => "execute_service_checks",
36 'ACCEPTING_PASSIVE_SVC_CHECKS' => "accept_passive_service_checks",
37 'EXECUTING_HOST_CHECKS' => "execute_host_checks",
38 'ACCEPTING_PASSIVE_HOST_CHECKS' => "accept_passive_host_checks",
39 'EVENT_HANDLERS' => "enable_event_handlers",
40 'OBSESSING_OVER_SVC_CHECKS' => "obsess_over_services",
41 'OBSESSING_OVER_HOST_CHECKS' => "obsess_over_hosts",
42 'FLAP_DETECTION' => "enable_flap_detection",
43 'PERFORMANCE_DATA' => "process_performance_data"
46 if ( isset( $cmd_name_mapping[ $naming ] ) )
47 $naming = $cmd_name_mapping[ $naming ];
49 if ( $method ) {
51 $cmd = new Command_Controller();
53 if ( $method === "submit" ) {
55 $info = $cmd->submit( $command );
56 return json::ok( $info );
58 } elseif ( $method === "commit" ) {
60 $status = Current_status_Model::instance()->program_status();
62 if ( isset( $status->$naming ) )
63 $state = $status->$naming;
64 $cmd->commit( $command );
66 if ( isset( $state ) )
67 return json::ok( array( "state" => $state ) );
68 else
69 return json::ok( array( ) );
77 /**
78 * Handle search queries from front page search field
80 public function global_search($q=false)
82 $q = $this->input->get('query', $q);
84 $result = $this->global_search_build_filter($q);
86 if( $result !== false ) {
87 $obj_type = $result[0];
88 $obj_name = $result[1];
89 $settings = $result[2];
90 $livestatus_options = $result[3];
92 $ls = Livestatus::instance();
93 $lsb = $ls->getBackend();
95 $livestatus_options['limit'] = Kohana::config('config.autocomplete_limit');
97 $data = $lsb->getTable($obj_type, $livestatus_options);
98 $obj_info = array();
99 $obj_data = array();
101 if ($data!==false) {
102 foreach ($data as $row) {
103 $row = (object)$row;
104 $obj_info[] = $obj_type == 'services' ? $row->{$settings['data']} . ';' . $row->{$settings['name_field']} : $row->{$settings['name_field']};
105 $obj_data[] = array($settings['path'], $row->{$settings['data']});
107 if (!empty($obj_data) && !empty($found_str)) {
108 $obj_info[] = $divider_str;
109 $obj_data[] = array('', $divider_str);
110 $obj_info[] = $found_str;
111 $obj_data[] = array('', $found_str);
114 $var = array('query' => $q, 'suggestions' => $obj_info, 'data' => $obj_data);
116 } else {
117 $var = array('query' => $q, 'suggestions' => array(), 'data' => array());
119 $json_str = json_encode($var);
120 echo $json_str;
124 * This is actually a local method for global_search to build the search query for live search.
126 * This method is public to make it testable. It doesn't interact with anything external, or take time, so it's no security issue...
128 * @param $q Search query
130 public function global_search_build_filter($q)
132 $parser = new ExpParser_SearchFilter();
134 try {
135 $parser->parse($q);
136 $obj_type = $parser->getLastObject();
137 $obj_name = $parser->getLastString();
138 } catch( ExpParserException $e ) {
139 $obj_type = 'hosts';
140 $obj_name = $q;
141 } catch( Exception $e ) {
142 return false;
145 $obj_data = array();
146 $obj_info = array();
148 if ($obj_type !== false) {
149 switch ($obj_type) {
150 case 'hosts': $settings = array( 'name_field' => 'name', 'data' => 'name', 'path' => '/listview/?q=[services] host.name="%s"' ); break;
151 case 'services': $settings = array( 'name_field' => 'description', 'data' => 'host_name', 'path' => '/extinfo/details/?type=service&host=%s&service=%s' ); break;
152 case 'hostgroups': $settings = array( 'name_field' => 'name', 'data' => 'name', 'path' => '/listview/?q=[hosts] in "%s"' ); break;
153 case 'servicegroups': $settings = array( 'name_field' => 'name', 'data' => 'name', 'path' => '/listview/?q=[services] in "%s"' ); break;
154 case 'comments': $settings = array( 'name_field' => 'comment_data', 'data' => 'host_name', 'path' => '/extinfo/details/?type=host&host=%s' ); break;
155 default: return false;
158 return array( $obj_type, $obj_name, $settings, array(
159 'columns' => array_unique( array($settings['name_field'], $settings['data']) ),
160 'filter' => array($settings['name_field'] => array( '~~' => str_replace('%','.*',$obj_name) ))
161 ) );
163 return false;
167 * fetch specific setting
169 public function get_setting()
171 $type = $this->input->post('type', false);
172 $page = $this->input->post('page', false);
173 if (empty($type))
174 return false;
175 $type = trim($type);
176 $page = trim($page);
177 $data = Ninja_setting_Model::fetch_page_setting($type, $page);
178 $setting = $data!==false ? $data->setting : false;
179 return json::ok(array($type => json_decode($setting)));
183 * Save a specific setting
185 public function save_page_setting()
187 $type = $this->input->post('type', false);
188 $page = $this->input->post('page', false);
189 $setting = $this->input->post('setting', false);
191 if (empty($type) || empty($page) || (empty($setting) && $setting !== "0"))
192 return false;
193 Ninja_setting_Model::save_page_setting($type, $page, $setting);
197 * Fetch translated help text
198 * Two parameters arre supposed to be passed through POST
199 * * controller - where is the translation?
200 * * key - what key should be fetched
202 public function get_translation()
204 $controller = $this->input->post('controller', false);
205 $key = $this->input->post('key', false);
207 if (empty($controller) || empty($key)) {
208 return false;
210 $controller = ucfirst($controller).'_Controller';
211 $result = call_user_func(array($controller,'_helptexts'), $key);
212 return $result;
216 * Fetch PNP image from supplied params
218 public function pnp_image()
220 $param = $this->input->post('param', false);
221 $param = pnp::clean($param);
222 $pnp_path = Kohana::config('config.pnp4nagios_path');
224 if ($pnp_path != '') {
225 $pnp_path .= '/image?'.$param;
227 $setting_key = $pnp_path;
229 if (strpos($param, 'source') === false) {
230 $source = Ninja_setting_Model::fetch_page_setting('source', $setting_key);
231 if ($source)
232 $pnp_path .= '&source='.$source->setting;
233 else
234 $pnp_path .= '&source=0';
237 $view = Ninja_setting_Model::fetch_page_setting('view', $setting_key, 1);
238 if ($view)
239 $pnp_path .= '&view='.$view->setting;
240 else
241 $pnp_path .= '&view=1';
243 $pnp_path .= '&display=image';
246 echo '<img src="'.$pnp_path.'" />';
250 * Save prefered graph for a specific param
252 public function pnp_default()
254 $param = $this->input->post('param', false);
255 $param = pnp::clean($param);
256 $pnp_path = Kohana::config('config.pnp4nagios_path');
258 if ($pnp_path != '') {
259 $source = intval($this->input->post('source', false));
260 $view = intval($this->input->post('view', false));
262 Ninja_setting_Model::save_page_setting('source', $pnp_path.'/image?'.$param, $source);
263 Ninja_setting_Model::save_page_setting('view', $pnp_path.'/image?'.$param, $view);
268 * Fetch comment for object
270 public function fetch_comments()
272 $host = $this->input->get('host', false);
273 $service = false;
275 if (strstr($host, ';')) {
276 # we have a service - needs special handling
277 $parts = explode(';', $host);
278 if (sizeof($parts) == 2) {
279 $host = $parts[0];
280 $service = $parts[1];
284 $data = _('Found no data');
285 $set = CommentPool_Model::all();
286 /* @var $set ObjectSet_Model */
287 $set = $set->reduce_by('host.name', $host, '=');
288 if($service !== false)
289 $set = $set->reduce_by('service.description', $service, '=');
291 if (count($set) > 0) {
292 $data = "<table><tr><th>"._("Timestamp")."</th><th>"._('Author')."</th><th>"._('Comment')."</th></tr>";
293 foreach ($set->it(array('entry_time', 'author', 'comment'),array()) as $row) {
294 $data .= '<tr><td>'.date(nagstat::date_format(), $row->get_entry_time()).'</td><td valign="top">'.$row->get_author().'</td><td width="400px">'.wordwrap($row->get_comment(), '50', '<br />').'</td></tr>';
296 $data .= '</table>';
299 echo $data;
303 * Worst methodname evah.
305 * Returns all the objects of the specified type that your user has
306 * permissions to view.
308 * @param $type string = false
310 public function group_member($type=false)
312 $type = $this->input->get('type', false);
314 $result = array();
315 switch ($type) {
316 case 'hostgroups':
317 case 'servicegroups':
318 case 'hosts':
319 foreach(Livestatus::instance()->{'get'.$type}(array(
320 'columns' => array('name')
321 )) as $row) {
322 $result[] = $row['name'];
324 break;
325 case 'services':
326 foreach(Livestatus::instance()->getServices(array(
327 'columns' => array('host_name', 'service_description')
328 )) as $row) {
329 $result[] = $row['host_name'].";".$row['service_description'];
331 break;
332 default:
333 json::fail("No object type given");
336 json::ok($result);
340 * Fetch available report periods for selected report type
342 public function get_report_periods()
344 $type = $this->input->post('type', 'avail');
345 if (empty($type))
346 return false;
348 $report_periods = Reports_Controller::_report_period_strings($type);
349 $periods = false;
350 if (!empty($report_periods)) {
351 foreach ($report_periods['report_period_strings'] as $periodval => $periodtext) {
352 $periods[] = array('optionValue' => $periodval, 'optionText' => $periodtext);
354 } else {
355 return false;
358 # add custom period
359 $periods[] = array('optionValue' => 'custom', 'optionText' => "* " . _('CUSTOM REPORT PERIOD') . " *");
361 echo json_encode($periods);
365 * Save a search for later use
367 public function save_search()
369 $search_name = $this->input->post('name', false);
370 $search_query = $this->input->post('query', false);
371 $search_description = $this->input->post('description', false);
372 $search_id = $this->input->post('search_id', false);
374 $model = new Saved_searches_Model();
375 $res = $model->save_search($search_query, $search_name, $search_description, $search_id);
377 echo ((int)$res != 0) ? (int)$res : 'Error';
381 * Remove a saved search
383 public function remove_search()
385 $search_id = $this->input->post('search_id', false);
386 $res = Saved_searches_Model::remove_search($search_id);
388 echo $res != false ? 'OK' : 'Error';
392 * Fetch a saved search by ID
394 public function fetch_saved_search()
396 $search_id = (int)$this->input->post('search_id', false);
397 if (empty($search_id)) {
398 echo "Error";
399 return false;
402 $res = Saved_searches_Model::get_search_by_id($search_id);
403 if ($res != false) {
404 $result = $res->current();
405 echo json_encode(array('search_name' => $result->search_name, 'search_query' => $result->search_query, 'search_description' => $result->search_description, 'search_id' => $result->id));
406 return true;
408 echo "Error";
409 return false;
412 public function fetch_saved_search_by_query() {
413 $query = $this->input->get('query', false);
414 $model = new Saved_searches_Model();
415 $result = $model->get_search_by_query($query)->as_array();
416 if(!$result) {
417 json::fail("'$query' has not yet been saved");
419 json::ok(current($result));