public function __construct($title, &$vars) { parent::__construct($title, $vars); $graphtypes = Operator::getGraphInfo(); $graphs = array(); foreach ($graphtypes as $type => $info) { $graphs[$type] = $info['title']; } $this->addVariable(_("Graph"), 'graph', 'enum', true, false, null, array($graphs)); }
} } catch (Horde_Exception $e) { //$notification->push(_("Invalid dates requested.")); $notification->push($e); $stats = array(); } } else { foreach ($session->get('operator', 'lastsearch/params', Horde_Session::TYPE_ARRAY) as $var => $val) { $vars->set($var, $val); } $data = $session->get('operator', 'lastsearch/data', Horde_Session::TYPE_ARRAY); } $graphs = array(); if (!empty($stats)) { $url = Horde::url('graphgen.php'); $graphtypes = Operator::getGraphInfo(); foreach ($graphtypes as $type => $info) { $graphs[$type] = $url->add(array('graph' => $type, 'key' => $cachekey)); } } $curgraph = $vars->get('graph'); $page_output->header(array('title' => _("Call Detail Records Graph"))); $notification->notify(array('listeners' => 'status')); $form->renderActive($renderer, $vars, Horde::url('viewgraph.php'), 'post'); if (!empty($stats) && !empty($graphs[$curgraph])) { echo '<br />'; echo '<img src="' . $graphs[$curgraph] . '"/><br />'; } $page_output->footer(); // Don't leave stale stats lying about $session->remove('operator', 'stats');
/** * Get summary call statistics per-month for a given time range, account and * destination. * * @param Horde_Date startdate Start of the statistics window * @param Horde_Date enddate End of the statistics window * @param string accountcode Name of the accont for statistics. Defaults * to null meaning all accounts. * @param string dcontext Destination of calls. Defaults to null. * * * @return array Array of call statistics. The key of each * element is the month name in date('Y-m') * format and the value being an array of * statistics for calls placed that month. * @throws Operator_Exception|Horde_Date_Exception */ protected function _getMonthlyCallStats($start, $end, $accountcode = null, $dcontext = null) { if (!is_a($start, 'Horde_Date') || !is_a($end, 'Horde_Date')) { Horde::log('Start ane end date must be Horde_Date objects.', 'ERR'); throw new Operator_Exception(_("Internal error. Details have been logged for the administrator.")); } /* Make sure we have a valid database connection. */ $this->_connect(); // Construct the queries we will be running below // Use 1=1 to make constructing the filter string easier $numcalls_query = 'SELECT MONTH(calldate) AS month, ' . 'YEAR(calldate) AS year, ' . 'COUNT(*) AS numcalls FROM ' . $this->_params['table'] . ' WHERE %s ' . 'GROUP BY year, month'; $minutes_query = 'SELECT MONTH(calldate) AS month, ' . 'YEAR(calldate) AS year, ' . 'SUM(duration)/60 AS minutes FROM ' . $this->_params['table'] . ' WHERE %s ' . 'GROUP BY year, month'; $failed_query = 'SELECT MONTH(calldate) AS month, ' . 'YEAR(calldate) AS year, ' . 'COUNT(disposition) AS failed FROM ' . $this->_params['table'] . ' ' . 'WHERE disposition="failed" AND %s ' . 'GROUP BY year, month'; // Shared SQL filter $filter = array(); $values = array(); // Filter by account code if ($accountcode !== null) { $filter[] = 'accountcode LIKE ?'; $values[] = $accountcode; } else { $filter[] = 'accountcode = ""'; } // Filter by destination context if ($dcontext !== null) { $filter[] = 'dcontext LIKE ?'; $values[] = $dcontext; } else { $filter[] = 'dcontext = ""'; } // Filter by the date range (filled in below) $filter[] = 'calldate >= ?'; $values[] = $start->strftime('%Y-%m-%d %T'); $filter[] = 'calldate < ?'; $values[] = $end->strftime('%Y-%m-%d %T'); $filterstring = implode(' AND ', $filter); $stats = array(); /* Log the query at a DEBUG log level. */ $sql = sprintf($numcalls_query, $filterstring); Horde::log(sprintf('Operator_Driver_asterisksql::getCallStats(): Values: %s', print_r($values, true)), 'DEBUG'); Horde::log(sprintf('Operator_Driver_asterisksql::getCallStats(): %s', $sql), 'DEBUG'); $numcalls_res = $this->_db->getAll($sql, $values, DB_FETCHMODE_ASSOC); if (is_a($numcalls_res, 'PEAR_Error')) { Horde::log($numcalls_res, 'ERR'); throw new Operator_Exception(_("Internal error. Details have been logged for the administrator.")); } $sql = sprintf($minutes_query, $filterstring); Horde::log(sprintf('Operator_Driver_asterisksql::getCallStats(): %s', $sql), 'DEBUG'); $minutes_res = $this->_db->getAll($sql, $values, DB_FETCHMODE_ASSOC); if (is_a($minutes_res, 'PEAR_Error')) { Horde::log($minutes_res, 'ERR'); throw new Operator_Exception(_("Internal error. Details have been logged for the administrator.")); } $sql = sprintf($failed_query, $filterstring); Horde::log(sprintf('Operator_Driver_asterisksql::getCallStats(): %s', $sql), 'DEBUG'); $failed_res = $this->_db->getAll($sql, $values, DB_FETCHMODE_ASSOC); if (is_a($failed_res, 'PEAR_Error')) { Horde::log($failed_res, 'ERR'); throw new Operator_Exception(_("Internal error. Details have been logged for the administrator.")); } // Normalize the results from the database. This is done because // the database will not return values if there are no data that match // the query. For example if there were no calls in the month of June // the results will not have any rows with data for June. Instead of // searching through the results for each month we stuff the values we // have into a temporary array and then create the return value below // using 0 values where necessary. $numcalls = array(); foreach ($numcalls_res as $row) { $numcalls[$row['year']][$row['month']] = $row['numcalls']; } $minutes = array(); foreach ($minutes_res as $row) { $minutes[$row['year']][$row['month']] = $row['minutes']; } $failed = array(); foreach ($failed_res as $row) { $failed[$row['year']][$row['month']] = $row['failed']; } $s_numcalls = array(); $s_minutes = array(); $s_failed = array(); while ($start->compareDate($end) <= 0) { $index = $start->strftime('%Y-%m'); $year = $start->year; $month = $start->month; if (empty($numcalls[$year]) || empty($numcalls[$year][$month])) { $s_numcalls[$index] = 0; } else { $s_numcalls[$index] = $numcalls[$year][$month]; } if (empty($minutes[$year]) || empty($minutes[$year][$month])) { $s_minutes[$index] = 0; } else { $s_minutes[$index] = $minutes[$year][$month]; } if (empty($failed[$year]) || empty($failed[$year][$month])) { $s_failed[$index] = 0; } else { $s_failed[$index] = $failed[$year][$month]; } // Find the first day of the next month $start->month++; } $info = Operator::getGraphInfo('numcalls'); $stats['numcalls'] = array($info['title'] => $s_numcalls); $info = Operator::getGraphInfo('minutes'); $stats['minutes'] = array($info['title'] => $s_minutes); // $info = Operator::getGraphInfo('failed'); // $stats['failed'] = array($info['title'] => $s_failed); return $stats; }
* See the enclosed file COPYING for license information (GPL). If you * did not receive this file, see http://www.horde.org/licenses/gpl. * * @author Ben Klang <*****@*****.**> */ require_once __DIR__ . '/lib/Application.php'; $operator = Horde_Registry::appInit('operator'); $cache =& $GLOBALS['cache']; // Work around warnings in Image_Graph // Needed for Image_Graph <= 0.7.2 and Image_Canvas <= 0.3.2 //error_reporting(E_NONE); //ini_set("display_errors", 0); //setlocale(LC_ALL, $registry->preferredLang()); //setlocale(LC_ALL, 'en'); $graphtype = Horde_Util::getFormData('graph'); $graphinfo = Operator::getGraphInfo($graphtype); $cachekey = Horde_Util::getFormData('key'); $stats = unserialize($cache->get($cachekey, 0)); // Create the graph image base. if (empty($graphinfo['imageX'])) { $graphinfo['imageX'] = 700; } if (empty($graphinfo['imageY'])) { $graphinfo['imageY'] = 600; } if (!isset($graphinfo['charttype'])) { $graphinfo['charttype'] = 'bar'; } if (!isset($graphinfo['markers'])) { $graphinfo['markers'] = true; }