diff --git a/README.md b/README.md index b58e4bf..5c5f1b8 100644 --- a/README.md +++ b/README.md @@ -131,6 +131,19 @@ community. After that you should open a feature request on * issue#61: Improve visual layout when viewing report +* issue#64: Running a scheduled report via crontab doesn't work + +* issue#66: Fix to issue causing reportit plugin to error / disable + +* Feature: Log reporting now utilises CLOG's regex parsing hooks to provide + direct links to the report/data item from the CLOG tabs in a similar mode to + the base Cacti methods + +* Feature: Email format can be set to None, so no attachment but still get + notification of report generation. + +* Feature: Reintroduced Emailing Functionality + * Feature: Reintroduced Graphs (basic functionality) * Feature: Reintroduced Subheaders diff --git a/lib/const_runtime.php b/lib/const_runtime.php index 69080d0..5194f5f 100644 --- a/lib/const_runtime.php +++ b/lib/const_runtime.php @@ -64,19 +64,19 @@ $runtime_messages = array( 1 => 'REPORTIT ERROR: PHP modul for RRDtool is not available.', - 2 => 'REPORTIT ERROR: No data items defined. Report[]', - 3 => 'REPORTIT ERROR: Startpoint is a part of future. Report[] Data item[]', - 4 => 'REPORTIT ERROR: No valid data found. Check your configuration. Report[]', - 5 => 'REPORTIT WARNING: RRDfetch: Report[] Data Item[]', - 6 => 'REPORTIT WARNING: End of working time is a part of future. Can only calculate data till now. Report[] Data item[]', - 7 => 'REPORTIT WARNING: No startpoints available. Check your working days! Report[] Data item[]', - 8 => 'REPORTIT WARNING: No values available. Report[] Data Item[]', + 2 => 'REPORTIT ERROR: No data items defined. RIReport[]', + 3 => 'REPORTIT ERROR: Startpoint is a part of future. RIReport[] RIDataItem[]', + 4 => 'REPORTIT ERROR: No valid data found. Check your configuration. RIReport[]', + 5 => 'REPORTIT WARNING: RRDfetch: RIReport[] RIDataItem[]', + 6 => 'REPORTIT WARNING: End of working time is a part of future. Can only calculate data till now. RIReport[] RIDataItem[]', + 7 => 'REPORTIT WARNING: No startpoints available. Check your working days! RIReport[] RIDataItem[]', + 8 => 'REPORTIT WARNING: No values available. RIReport[] RIDataItem[]', 9 => 'REPORTIT ERROR: Unable to connect to RRDtool server.', - 10 => 'REPORTIT ERROR: Data template for report[] has been locked during the cronjob', - 11 => 'REPORTIT WARNING: Unknown timezone: . Please update configuration of Report [] Data item[]', - 12 => 'REPORTIT ERROR: Report[]', - 13 => 'REPORTIT WARNING: Report[]', - 14 => 'REPORTIT STATS: Report[]', + 10 => 'REPORTIT ERROR: Data template for RIReport[] has been locked during the cronjob', + 11 => 'REPORTIT WARNING: Unknown timezone: . Please update configuration of Report [] RIDataItem[]', + 12 => 'REPORTIT ERROR: RIReport[]', + 13 => 'REPORTIT WARNING: RIReport[]', + 14 => 'REPORTIT STATS: RIReport[]', 15 => 'REPORTIT WARNING: ', 16 => 'REPORTIT NOTICE: ', 17 => 'REPORTIT ERROR: ' diff --git a/lib/funct_export.php b/lib/funct_export.php index 8aecf6c..c1bf082 100644 --- a/lib/funct_export.php +++ b/lib/funct_export.php @@ -55,17 +55,20 @@ function export_to_CSV(&$data) { $report_measurands = $data['report_measurands']; $report_variables = $data['report_variables']; + $csv_column_s = read_config_option('reportit_csv_column_s'); + $csv_decimal_s = read_config_option('reportit_csv_decimal_s'); + /* load user settings */ if ($run_scheduled !== true) { /* request via web */ $no_formatting = 0; - $c_sep = $csv_c_sep[read_config_option('reportit_csv_column_s')]; - $d_sep = $csv_d_sep[read_config_option('reportit_csv_decimal_s')]; + $c_sep = $csv_c_sep[$csv_column_s]; + $d_sep = $csv_d_sep[$csv_decimal_s]; } else { /* request via cli */ $no_formatting = $report_data['autoexport_no_formatting']; - $c_sep = $csv_c_sep[get_graph_config_option('reportit_csv_column_s', $report_data['user_id'])]; - $d_sep = $csv_d_sep[get_graph_config_option('reportit_csv_decimal_s', $report_data['user_id'])]; + $c_sep = $csv_c_sep[$csv_column_s]; + $d_sep = $csv_d_sep[$csv_decimal_s]; } /* plugin version */ $info = plugin_reportit_version(); diff --git a/lib/funct_mailer.php b/lib/funct_mailer.php index 309cf1c..a5ad0a6 100644 --- a/lib/funct_mailer.php +++ b/lib/funct_mailer.php @@ -1,18 +1,18 @@ name format - * @arg $bcc - either a string of comma delimited email addresses, or an array of addresses in email_address => name format - * @arg $replyto - a string email address, or an array in array(email_address, name format) - * @arg $subject - the email subject - * @arg $body - the email body, in HTML format. If content_text is not set, the function v1_2_0_will attempt to extract - * from the HTML format. - * @arg $body_text - the email body in TEXT format. If set, it will override the stripping tags method +/** mailer - function to send mails to users + * @arg $from - single contact (see below) + * @arg $to - single or multiple contacts (see below) + * @arg $cc - none, single or multiple contacts (see below) + * @arg $bcc - none, single or multiple contacts (see below) + * @arg $replyto - none, single or multiple contacts (see below) + * note that this value is used when hitting reply (overriding the default of using from) + * @arg $subject - the email subject + * @arg $body - the email body, in HTML format. If content_text is not set, the function will attempt to extract + * from the HTML format. + * @arg $body_text - the email body in TEXT format. If set, it will override the stripping tags method * @arg $attachments - the emails attachments as an array - * @arg $headers - an array of name value pairs representing custom headers. - * @arg $html - if set to true, html is the default, otherwise text format will be used + * @arg $headers - an array of name value pairs representing custom headers. + * @arg $html - if set to true, html is the default, otherwise text format will be used * * For contact parameters, they can accept arrays containing zero or more values in the forms of: * 'email@email.com,email2@email.com,email3@email.com' @@ -20,9 +20,9 @@ * array(array('email' => 'email1@email.com', 'name' => 'My email'), array('email' => 'email2@email.com', * 'name' => 'Your email'), array('email' => 'email3@email.com', 'name' => 'Whose email')) * - * The $from and $replyto field will only use the first contact specified. If no contact is provided for $replyto + * The $from field will only use the first contact specified. If no contact is provided for $replyto * then $from is used for that too. If $from is empty, it will default to cacti@ or if no server name can - * be found, it will use cacti@cacit.net + * be found, it will use cacti@cacti.net * * The $attachments parameter may either be a single string, or a list of attachments * either as strings or an array. The array can have the following keys: @@ -38,13 +38,13 @@ function v1_2_0_mailer($from, $to, $cc, $bcc, $replyto, $subject, $body, $body_text = '', $attachments = '', $headers = '', $html = true) { global $config; + include_once($config['include_path'] . '/phpmailer/PHPMailerAutoload.php'); + // Set the to information if (empty($to)) { return __('Mailer Error: No TO address set!!
If using the Test Mail link, please set the Alert e-mail setting.'); } - include_once($config['include_path'] . '/vendor/phpmailer/PHPMailerAutoload.php'); - // Create the PHPMailer instance $mail = new PHPMailer; @@ -57,7 +57,6 @@ function v1_2_0_mailer($from, $to, $cc, $bcc, $replyto, $subject, $body, $body_t } $how = read_config_option('settings_how'); - echo "how = $how\n"; if ($how < 0 || $how > 2) { $how = 0; } @@ -137,7 +136,7 @@ function v1_2_0_mailer($from, $to, $cc, $bcc, $replyto, $subject, $body, $body_t } } - $fromText = add_email_details(array($from), $result, array($mail, 'setFrom')); + $fromText = v1_2_0_add_email_details(array($from), $result, array($mail, 'setFrom')); if ($result == false) { cacti_log('ERROR: ' . $mail->ErrorInfo, false, 'MAILER'); @@ -146,7 +145,7 @@ function v1_2_0_mailer($from, $to, $cc, $bcc, $replyto, $subject, $body, $body_t // Convert $to variable to proper array structure $to = v1_2_0_parse_email_details($to); - $toText = add_email_details($to, $result, array($mail,'addAddress')); + $toText = v1_2_0_add_email_details($to, $result, array($mail,'addAddress')); if ($result == false) { cacti_log('ERROR: ' . $mail->ErrorInfo, false, 'MAILER'); @@ -154,7 +153,7 @@ function v1_2_0_mailer($from, $to, $cc, $bcc, $replyto, $subject, $body, $body_t } $cc = v1_2_0_parse_email_details($cc); - $ccText = add_email_details($cc, $result, array($mail,'addCC')); + $ccText = v1_2_0_add_email_details($cc, $result, array($mail,'addCC')); if ($result == false) { cacti_log('ERROR: ' . $mail->ErrorInfo, false, 'MAILER'); @@ -162,7 +161,7 @@ function v1_2_0_mailer($from, $to, $cc, $bcc, $replyto, $subject, $body, $body_t } $bcc = v1_2_0_parse_email_details($bcc); - $bccText = add_email_details($bcc, $result, array($mail,'addBCC')); + $bccText = v1_2_0_add_email_details($bcc, $result, array($mail,'addBCC')); if ($result == false) { cacti_log('ERROR: ' . $mail->ErrorInfo, false, 'MAILER'); @@ -170,7 +169,7 @@ function v1_2_0_mailer($from, $to, $cc, $bcc, $replyto, $subject, $body, $body_t } $replyto = v1_2_0_parse_email_details($replyto); - $replyText = add_email_details($replyto, $result, array($mail,'addReplyTo')); + $replyText = v1_2_0_add_email_details($replyto, $result, array($mail,'addReplyTo')); if ($result == false) { cacti_log('ERROR: ' . $mail->ErrorInfo, false, 'MAILER'); @@ -206,8 +205,8 @@ function v1_2_0_mailer($from, $to, $cc, $bcc, $replyto, $subject, $body, $body_t $i = 0; // Handle Graph Attachments - if (!empty($attachments)) { - $attachments = array($attachments); + if (!empty($attachments) && !is_array($attachments)) { + $attachments = array('attachment' => $attachments); } if (is_array($attachments) && cacti_sizeof($attachments)) { @@ -320,7 +319,7 @@ function v1_2_0_add_email_details($emails, &$result, callable $addFunc) { if (!empty($addFunc)) { $result = $addFunc($e['email'], $e['name']); } - $arrText[] = create_emailtext($e); + $arrText[] = v1_2_0_create_emailtext($e); } } $text = implode(',', $arrText); @@ -344,7 +343,7 @@ function v1_2_0_parse_email_details($emails, $max_records = 0, $details = array( foreach($emails as $email) { //echo "parse_email_details(): checking '" . trim($email) . "' ... \n"; $e = trim($email); - $d = split_emaildetail($e); + $d = v1_2_0_split_emaildetail($e); $details[] = $d; } } else { diff --git a/lib/funct_shared.php b/lib/funct_shared.php index ca726ad..ad35bd7 100644 --- a/lib/funct_shared.php +++ b/lib/funct_shared.php @@ -1234,29 +1234,47 @@ function send_scheduled_email($report_id){ $from[] = read_config_option('settings_from_email'); $from[] = read_config_option('settings_from_name'); - $to = array_rekey(db_fetch_assoc_prepared('SELECT email, name + $to = db_fetch_assoc_prepared('SELECT email, name FROM plugin_reportit_recipients WHERE report_id = ?', - array($report_id)), 'email', 'name'); - - /* define additional attachment settings */ - $filename = str_replace('', $report_id, read_config_option('reportit_exp_filename') . ".$file_type"); - $export_function = "export_to_" . $format; + array($report_id)); - /* load export data and define the attachment file */ $attachment = array(); $data = ''; - if (function_exists($export_function)) { - $data = get_prepared_report_data($report_id, 'export'); - if ($data == '') return('Export failed'); - $data = $export_function($data); - $attachment = array( - 'attachmet' => $filename, - 'mime_type' => $mime_type, - 'inline' => 'attachment', - ); + + if ($format != 'None') { + /* define additional attachment settings */ + $filebase = read_config_option('reportit_exp_filename'); + if (empty($filebase)) { + $filebase = 'report_'; + } + + $dirbase = dirname($filebase); + if (empty($dirbase) || $dirbase == '.') { + $dirbase = sys_get_temp_dir(); + } + + $filebase = $dirbase . '/' . $filebase . ".$file_type"; + $filename = str_replace('', $report_id, $filebase); + $export_function = "export_to_" . $format; + + echo "Attachment: $filename\n"; + + /* load export data and define the attachment file */ + if (function_exists($export_function)) { + $data = get_prepared_report_data($report_id, 'export'); + if ($data == '') return('Export failed'); + $data = $export_function($data); + $attachment = array( + 'attachment' => $filename, + 'mime_type' => $mime_type, + 'inline' => 'attachment', + ); + file_put_contents($filename, $data); + } else { + echo "Missing function '$export_function'\n"; + } } - file_put_contents($filename, $data); if (cacti_version_compare(CACTI_VERSION, '1.2.0', '>')) { $mailer_func = "mailer"; @@ -1265,7 +1283,7 @@ function send_scheduled_email($report_id){ $mailer_func = "v1_2_0_mailer"; } - return $mailer_func($from, $to, '', '', '', $subject, $body, '', $attachment, '', true); + return $mailer_func($from, $to, '', '', '', $subject, $body, '', array($attachment), '', true); } function xml_to_string($xml_object, $keep_spaces = true) { diff --git a/rrdlist.php b/rrdlist.php index 62c3323..bb36062 100644 --- a/rrdlist.php +++ b/rrdlist.php @@ -328,10 +328,12 @@ function rrdlist_edit() { FROM plugin_reportit_data_items AS a LEFT JOIN data_template_data AS b ON b.local_data_id=a.id - WHERE a.id = ? - AND report_id = ?', - array(get_request_var('id'), get_request_var('report_id'))); + WHERE a.id = ?', + array(get_request_var('id'))); + if ($rrdlist_data !== false && sizeof($rrdlist_data)) { + set_request_var('report_id', $rrdlist_data['report_id']); + } $header_label = __('Data Item [edit: %s]', $rrdlist_data['name_cache'], 'reportit'); /* start with HTML output */ diff --git a/runtime.php b/runtime.php index 7a47c34..e5fb24f 100644 --- a/runtime.php +++ b/runtime.php @@ -194,23 +194,20 @@ function run_error($code, $RID = 0, $DID = 0, $notice='') { $run_repl_view = array( $notice, $PATH_RID_VIEW, $PATH_DID_VIEW); $run_repl_fin = array( $notice, $RID, $DID); - if($run_scheduled) { - $run_logging = str_replace($run_search, $run_repl_log, $runtime_messages[$code]); - $run_logging = str_replace($run_search, $run_repl_fin, $run_logging); - - if( (strpos($run_logging, 'ERROR:')!== false & read_config_option('log_verbosity', true)>POLLER_VERBOSITY_NONE) | - (strpos($run_logging, 'WARNING:') !== false & read_config_option('log_verbosity', true)>POLLER_VERBOSITY_LOW) | - (strpos($run_logging, 'NOTICE:') !== false & read_config_option('log_verbosity', true)>POLLER_VERBOSITY_LOW) - ) { - cacti_log($run_logging, false, 'PLUGIN'); - } + $run_logging = str_replace($run_search, $run_repl_fin, $runtime_messages[$code]); + + $log_level = POLLER_VERBOSITY_NONE; + if (strpos($run_logging, 'ERROR:') !== false) { + $log_level = POLLER_VERBOSITY_LOW; + } elseif (strpos($run_logging, 'WARNING:') !== false) { + $log_level = POLLER_VERBOSITY_MEDIUM; + } elseif (strpos($run_logging, 'NOTICE:') !== false) { + $log_level = POLLER_VERBOSITY_MEDIUM; + } - if($run_verb) { - $date = date("m/d/Y h:i:s A"); - $output = "$date - " . str_replace($run_search, $run_repl_fin, $runtime_messages[$code]) . "\n"; - print $output; - } - }else { + cacti_log($run_logging, $run_verb, 'PLUGIN', $log_level); + + if(!$run_scheduled) { $run_output = str_replace($run_search, $run_repl_view, $runtime_messages[$code]); $run_output = str_replace($run_search, $run_repl_fin, $run_output); $run_return[] = $run_output; @@ -732,12 +729,9 @@ function runtime($report_id) { } /* create and send out an email */ - if(read_config_option('reportit_email') == 'bad') { - echo "Report:\n"; - var_dump($report_definitions['report']); + if(read_config_option('reportit_email') == 'on') { if($report_definitions['report']['auto_email'] == 'on') { $error = send_scheduled_email($report_id); - echo "$error = send_scheduled_email($report_id);\n"; if($error) { run_error(13, $report_id, 0, "EMAIL: $error"); }else { diff --git a/setup.php b/setup.php index 1c91e61..1753990 100644 --- a/setup.php +++ b/setup.php @@ -29,7 +29,7 @@ function plugin_reportit_install() { api_plugin_register_hook('reportit', 'config_arrays', 'reportit_config_arrays', 'setup.php'); api_plugin_register_hook('reportit', 'config_settings', 'reportit_config_settings', 'setup.php'); api_plugin_register_hook('reportit', 'poller_bottom', 'reportit_poller_bottom', 'setup.php'); - + api_plugin_register_hook('reportit', 'clog_regex_array', 'reportit_clog_regex_array', 'setup.php'); reportit_system_setup(); } @@ -668,3 +668,69 @@ function reportit_poller_bottom() { } } } + +function reportit_clog_regex_array($regex_array) { + $regex_array[] = array('name' => 'RIReport', 'regex' => '( RIReport\[)([, \d]+)(\])', 'func' => 'reportit_clog_regex_report'); + $regex_array[] = array('name' => 'RIDataItem', 'regex' => '( RIDataItem\[)([, \d]+)(\])', 'func' => 'reportit_clog_regex_dataitem'); + return $regex_array; +} + +function reportit_clog_regex_report($matches) { + global $config; + + $result = $matches[0]; + + $report_ids = explode(',',str_replace(" ","",$matches[2])); + if (cacti_sizeof($report_ids)) { + $result = ''; + $reports = db_fetch_assoc_prepared('SELECT id, description + FROM plugin_reportit_reports + WHERE id in (?)', + array(implode(',',$report_ids))); + + $reportDescriptions = array(); + if (cacti_sizeof($reports)) { + foreach ($reports as $report) { + $reportDescriptions[$report['id']] = html_escape($report['description']); + } + } + + foreach ($report_ids as $report_id) { + $result .= $matches[1].'' . (isset($reportDescriptions[$report_id]) ? $reportDescriptions[$report_id]:$report_id) . '' . $matches[3]; + } + } + + return $result; +} + +function reportit_clog_regex_dataitem($matches) { + global $config; + + $result = $matches[0]; + + $dataitem_ids = explode(',',str_replace(" ","",$matches[2])); + if (cacti_sizeof($dataitem_ids)) { + $result = ''; + $dataitems = db_fetch_assoc_prepared('SELECT a.id, a.report_id, b.name_cache as description + FROM plugin_reportit_data_items AS a + LEFT JOIN data_template_data AS b + ON b.local_data_id = a.id + WHERE a.id in (?)', + array(implode(',',$dataitem_ids))); + + $dataitemDescriptions = array(); + $dataitemReports = array(); + if (cacti_sizeof($dataitems)) { + foreach ($dataitems as $dataitem) { + $dataitemReports[$dataitem['id']] = $dataitem['report_id']; + $dataitemDescriptions[$dataitem['id']] = html_escape($dataitem['description']); + } + } + + foreach ($dataitem_ids as $dataitem_id) { + $result .= $matches[1].'' . (isset($dataitemDescriptions[$dataitem_id]) ? $dataitemDescriptions[$dataitem_id]:$dataitem_id) . '' . $matches[3]; + } + } + + return $result; +}