Merge branch 'maint/7.0'
[ninja.git] / modules / reports / controllers / base_reports.php
blob406b8bd2cea8a1ed2957dedd39b6723cee6856d4
1 <?php defined('SYSPATH') OR die('No direct access allowed.');
3 /**
4 * Base-class that report controllers build on.
6 * Might have been called Report_controller, had that name not been busy.
7 */
8 abstract class Base_reports_Controller extends Authenticated_Controller
10 /** All states, translated. Only used where actually translating them would break stuff. */
11 protected $state_values = false;
13 /** Useless base variable jay */
14 protected $histogram_link = "histogram/generate";
16 /** The type of this report. Usually based on controller name, but not always. */
17 public $type = false;
19 /** A report_option object */
20 protected $options = false;
22 /** Sanity-checks */
23 public function __construct() {
24 if ($this->type === false)
25 die("You must set \$type in ".get_class($this));
27 parent::__construct();
29 $this->state_values = array(
30 'OK' => _('OK'),
31 'WARNING' => _('WARNING'),
32 'UNKNOWN' => _('UNKNOWN'),
33 'CRITICAL' => _('CRITICAL'),
34 'PENDING' => _('PENDING'),
35 'UP' => _('UP'),
36 'DOWN' => _('DOWN'),
37 'UNREACHABLE' => _('UNREACHABLE')
40 # When run from cron-job, or mailing out reports from gui, we need access
41 if(Router::$method == 'generate' && !Auth::instance()->get_user()->logged_in() && PHP_SAPI == 'cli') {
42 $op5_auth = Op5Auth::factory(array('session_key' => false));
43 $op5_auth->force_user(new Op5User_AlwaysAuth());
46 $this->template->disable_refresh = true;
49 /** Controller method that should render a form for creating a report */
50 abstract public function index($input = false);
51 /** Controller method that should render a report */
52 abstract public function generate($input = false);
54 /**
55 * Generate PDF instead of normal rendering. Uses shell
57 * Assumes that $this->template is set up correctly
59 protected function generate_pdf()
61 $this->template->base_href = 'https://localhost'.url::base();
63 # not using exec, so STDERR (used for status info) will be loggable
64 $pipe_desc = array(
65 0 => array('pipe', 'r'),
66 1 => array('pipe', 'w'),
67 2 => array('pipe', 'w'));
68 $pipes = false;
70 $command = Kohana::config('reports.pdf_command');
71 $this->log->log('debug', "Running pdf generation command '$command'");
72 $process = proc_open($command, $pipe_desc, $pipes, DOCROOT);
74 if (is_resource($process)) {
75 // Render and store output
76 $content = $this->template->render();
77 $this->auto_render = false;
79 $filename = $this->type;
80 if ($this->options['schedule_id']) {
81 $schedule_info = Scheduled_reports_Model::get_scheduled_data($this->options['schedule_id']);
82 if ($schedule_info)
83 $filename = $schedule_info['filename'];
85 $months = date::abbr_month_names();
86 $month = $months[date('m')-1]; // January is [0]
87 $filename = preg_replace("~\.pdf$~", null, $filename)."_".date("Y_").$month.date("_d").'.pdf';
89 fwrite($pipes[0], $content);
90 fclose($pipes[0]);
92 $out = stream_get_contents($pipes[1]);
93 $err = stream_get_contents($pipes[2]);
94 if (trim($out)) {
95 header("Content-disposition: attachment; filename=$filename");
96 header('Content-Type: application/pdf');
97 header("Pragma: public");
98 header("Expires: 0");
99 header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
100 header("Cache-Control: private", false);
101 header("Content-Transfer-Encoding: binary");
102 echo $out;
103 } else {
104 $this->log->log('error', $err);
106 fclose($pipes[1]);
107 fclose($pipes[2]);
108 proc_close($process);
109 } else {
110 $this->log->log('error', "Tried running the following command but was unsuccessful:");
111 $this->log->log('error', $command);
116 * Save a report via ajax call
117 * Called from reports.js
118 * @return JSON string
120 public function save($input = false)
122 if(!request::is_ajax()) {
123 $msg = _('Only Ajax calls are supported here');
124 die($msg);
127 $this->setup_options_obj($input);
129 $this->auto_render=false;
131 $saved = $this->options->save($message);
132 if ($saved) {
133 return json::ok(array('status_msg' => _("Report was successfully saved"), 'report_id' => $this->options['report_id']));
135 return json::fail(array('error' => sprintf(_('Unable to save this report: %s'), $message)));
139 * Delete a saved report
141 public function delete() {
142 if(!request::is_ajax()) {
143 $msg = _('Only Ajax calls are supported here');
144 die($msg);
147 $id = $this->input->post('report_id');
148 if (!$id)
149 return json::fail(array('error' => _('No id supplied')));
151 $this->setup_options_obj(array('report_id' => $id));
152 if (!$this->options['report_name'])
153 return json::fail(array('error' => _("Couldn't find saved report")));
154 if ($this->options->delete())
155 return json::ok(array('success' =>_('Report deleted')));
156 return json::fail(array('error' => _("Couldn't delete report: unknown error")));
160 * Helper that makes sure a Report_options object is setup and available
162 protected function setup_options_obj($input = false, $type = false)
164 if ($this->options) // If a child class has already set this, leave it alone
165 return;
166 $this->options = Report_options::setup_options_obj($type ? $type : $this->type, $input);
167 $this->template->set_global('options', $this->options);
168 $this->template->set_global('type', $this->type);
172 * @param $options Report_options
174 function set_options(Report_options $options)
176 $this->options = $options;
180 * Determine the name of the state
182 protected function _state_string_name($type='host', $state=false) {
183 $type = strtolower($type);
185 if ($type === "host") {
186 return Reports_Model::$host_states[$state];
187 } elseif ($type === "service") {
188 return Reports_Model::$service_states[$state];
191 return "N/A";
195 * So this static method that random code everywhere assumes exist doesn't even have a fallback defined?
196 * Yeah, that's good code...
198 public static function _helptexts($id)
200 $helptexts = array(
201 'report-type' => _("Select the preferred report type. Hostgroup, Host, Servicegroup or Service. ".
202 "To include objects of the given type in the report, select the objects from the left list and click on ".
203 "the right pointing arrow. To exclude objects from the report, select the objects from the right list ".
204 "and click on the left pointing arrow."),
205 'reporting_period' => _("Choose from a set of predefined report periods or choose &quot;CUSTOM REPORT PERIOD&quot; ".
206 "to manually specify Start and End date."),
207 'report_time_period' => _("What time should the report be created for. Tip: This can be used for SLA reporting."),
208 'description' => _("Optionally add a description to this report, such as an explanation of what the report conveys. Plain text only."),
209 "skin" => _("Choose a skin for your summary report."),
210 "standardreport" => _("Choose the type of report you want from the list of predefined summary reports."),
211 "summary_type" => _('The format of the summary. &quot;Most recent alerts&quot; simply lists alerts, &quot;Top alert producers&quot; orders host and/or services by the one that has notified the most recently, and &quot;Alert totals&quot; sums up the number of alerts per selected object'),
212 "summary_items" => _("Enter the number of items you wish the report to contain."),
213 "alert_types" => _("Select whether to include only host alerts, service alerts, or both"),
214 "state_types" => _("Whether to include only hard alerts, soft alerts, or both"),
215 "host_states" => _("Restrict which state(s) you're interested in hosts entering"),
216 "service_states" => _("Restrict which state(s) you're interested in services entering"),
217 "include_long_output" => _("In views that displays individual alerts, include the full check output, instead of only the first line"),
218 'filter' => _("Free text search, matching the objects in the left list below"),
219 'saved_reports' => _("A list of all your saved reports. To load them, select the report you wish to generate and click select."),
222 if (array_key_exists($id, $helptexts)) {
223 echo $helptexts[$id];
224 } else {
225 echo sprintf(_("This helptext ('%s') is not translated yet"), $id);
230 * All reports must display the time range they cover, and this helper
231 * helps them do so with some amount of consistency.
233 * @param $date_format string Format string for date(), probably nagstat::date_format()
234 * @returns string Formatted date for this report
236 protected function format_report_time($date_format)
238 if($this->options['report_period'] && $this->options['report_period'] != 'custom')
239 $report_time_formatted = sprintf(
240 _('%s (%s to %s)'),
241 $this->options->get_value('report_period'),
242 "<strong>".date($date_format, $this->options['start_time'])."</strong>",
243 "<strong>".date($date_format, $this->options['end_time'])."</strong>"
245 else
246 $report_time_formatted = sprintf(_("%s to %s"),
247 date($date_format, $this->options['start_time']),
248 date($date_format, $this->options['end_time']));
250 if($this->options['rpttimeperiod'] != '')
251 $report_time_formatted .= " - {$this->options['rpttimeperiod']}";
252 return $report_time_formatted;