From ec92df8f634fd8a238249d9c767b0aceb3808285 Mon Sep 17 00:00:00 2001 From: Ben Klang Date: Thu, 3 Jul 2008 14:29:15 +0000 Subject: [PATCH] * Change default page to graphs * Limit number of search results to a number set in Prefs (default: 100) * Add call summary statistics to Search page * Don't cache CDR search results in the session * Add menu icons ToDo: Allow paging through larger result set on search page --- config/prefs.php.dist | 11 ++++++++-- index.php | 4 ++-- lib/Driver/asterisksql.php | 45 +++++++++++++++++++++++++++++++++----- lib/Form/SearchCDR.php | 6 ++--- lib/Operator.php | 6 ++--- search.php | 25 +++++++++++++++------ templates/search/header.inc | 7 ++++++ themes/graphics/graphs.png | Bin 0 -> 478 bytes themes/silver/graphics/graphs.png | Bin 0 -> 710 bytes viewgraph.php | 20 ++++++++++------- 10 files changed, 94 insertions(+), 30 deletions(-) create mode 100644 themes/graphics/graphs.png create mode 100644 themes/silver/graphics/graphs.png diff --git a/config/prefs.php.dist b/config/prefs.php.dist index 21b0e8204..2c5160e94 100644 --- a/config/prefs.php.dist +++ b/config/prefs.php.dist @@ -1,6 +1,6 @@ _("Options"), 'label' => _("Display Preferences"), 'desc' => _("Set default display parameters."), - 'members' => array('rowsperpage', 'columns') + 'members' => array('rowsperpage', 'resultlimit', 'columns') ); $_prefs['rowsperpage'] = array( @@ -20,6 +20,13 @@ $_prefs['rowsperpage'] = array( 'desc' => _("The columns to be displayed on the Call Detail Review screen") ); +$_prefs['resultlimit'] = array( + 'value' => 100, + 'locked' => false, + 'shared' => false, + 'type' => 'number', + 'desc' => _("Limit the number of CDR results when searching to this number") +); $_prefs['columns'] = array( 'value' => 'a:18:{i:0;s:11:"accountcode";i:1;s:3:"src";i:2;s:3:"dst";i:3;s:8:"dcontext";i:4;s:4:"clid";i:5;s:7:"channel";i:6;s:10:"dstchannel";i:7;s:7:"lastapp";i:8;s:8:"lastdata";i:9;s:5:"start";i:10;s:6:"answer";i:11;s:3:"end";i:12;s:8:"duration";i:13;s:7:"billsec";i:14;s:11:"disposition";i:15;s:8:"amaflags";i:16;s:9:"userfield";i:17;s:8:"uniqueid";}', diff --git a/index.php b/index.php index c5a58ccdb..bab9245f4 100644 --- a/index.php +++ b/index.php @@ -1,6 +1,6 @@ * @@ -19,4 +19,4 @@ if (!$operator_configured) { array('conf.php')); } -require OPERATOR_BASE . '/search.php'; +require OPERATOR_BASE . '/viewgraph.php'; diff --git a/lib/Driver/asterisksql.php b/lib/Driver/asterisksql.php index 799b70b7c..b990d8f6b 100644 --- a/lib/Driver/asterisksql.php +++ b/lib/Driver/asterisksql.php @@ -20,7 +20,7 @@ * The table structure can be created by the scripts/sql/operator_foo.sql * script. * - * $Horde: incubator/operator/lib/Driver/asterisksql.php,v 1.7 2008/07/01 22:25:01 bklang Exp $ + * $Horde: incubator/operator/lib/Driver/asterisksql.php,v 1.8 2008/07/03 14:29:17 bklang Exp $ * * Copyright 2007-2008 The Horde Project (http://www.horde.org/) * @@ -76,7 +76,8 @@ class Operator_Driver_asterisksql extends Operator_Driver { * * @return boolean|PEAR_Error True on success, PEAR_Error on failure. */ - function getData($start, $end, $accountcode = null, $dcontext = null) + function getData($start, $end, $accountcode = null, $dcontext = null, + $rowstart = 0, $rowlimit = 100) { // Use the query to make the MySQL driver look like the CDR-CSV driver @@ -88,6 +89,16 @@ class Operator_Driver_asterisksql extends Operator_Driver { $filter = array(); $values = array(); + if (!is_numeric($rowstart)) { + Horde::logMessage('Invalid start row requested.', __FILE__, __LINE__, PEAR_LOG_ERR); + return PEAR::raiseError(_("Internal error. Details have been logged for the administrator.")); + } + if (!is_numeric($rowlimit)) { + Horde::logMessage('Invalid row limit requested.', __FILE__, __LINE__, PEAR_LOG_ERR); + return PEAR::raiseError(_("Internal error. Details have been logged for the administrator.")); + } + + // Start Date if (!is_a($start, 'Horde_Date')) { $start = new Horde_Date($start); @@ -130,11 +141,35 @@ class Operator_Driver_asterisksql extends Operator_Driver { $filterstring = implode(' AND ', $filter); $sql = sprintf($sql, $filterstring); /* Log the query at a DEBUG log level. */ - Horde::logMessage(sprintf('Operator_Driver_asterisksql::getData(): %s', $sql), - __FILE__, __LINE__, PEAR_LOG_DEBUG); + Horde::logMessage(sprintf('Operator_Driver_asterisksql::getData(): %s', $sql), __FILE__, __LINE__, PEAR_LOG_DEBUG); + + /* Execute the query. */ + $res = $this->_db->limitQuery($sql, $rowstart, $rowlimit, $values); + if (is_a($res, 'PEAR_Error')) { + Horde::logMessage($res, __FILE__, __LINE__, PEAR_LOG_ERR); + return PEAR::raiseError(_("Internal error. Details have been logged for the administrator.")); + } + + $data = array(); + while ($row = $res->fetchRow(DB_FETCHMODE_ASSOC)) { + $data[] = $row; + } + + // Get summary statistics on the requested criteria + $sql = 'SELECT COUNT(*) AS numcalls, SUM(duration)/60 AS minutes, ' . + 'SUM(CASE disposition WHEN "FAILED" THEN 1 ELSE 0 END) AS ' . + 'failed FROM ' . $this->_params['table'] . ' WHERE %s'; + $sql = sprintf($sql, $filterstring); + Horde::logMessage(sprintf('Operator_Driver_asterisksql::getData(): %s', $sql), __FILE__, __LINE__, PEAR_LOG_DEBUG); /* Execute the query. */ - return $this->_db->getAll($sql, $values, DB_FETCHMODE_ASSOC); + $res = $this->_db->getRow($sql, $values, DB_FETCHMODE_ASSOC); + if (is_a($res, 'PEAR_Error')) { + Horde::logMessage($res, __FILE__, __LINE__, PEAR_LOG_ERR); + return PEAR::raiseError(_("Internal error. Details have been logged for the administrator.")); + } + + return array_merge($data, $res); } /** diff --git a/lib/Form/SearchCDR.php b/lib/Form/SearchCDR.php index 9e7153d06..b0d2a47cd 100644 --- a/lib/Form/SearchCDR.php +++ b/lib/Form/SearchCDR.php @@ -2,7 +2,7 @@ /** * SearchCDRForm Class * - * $Horde: incubator/operator/lib/Form/SearchCDR.php,v 1.3 2008/07/01 22:25:01 bklang Exp $ + * $Horde: incubator/operator/lib/Form/SearchCDR.php,v 1.4 2008/07/03 14:29:18 bklang Exp $ * * Copyright 2008 Alkaloid Networks LLC * @@ -15,11 +15,11 @@ class SearchCDRForm extends Horde_Form { - function SearchCDRForm(&$vars) + function SearchCDRForm($title, &$vars) { global $operator_driver; - parent::Horde_Form($vars, _("Search CDR Data")); + parent::Horde_Form($vars, $title); // FIXME: Generate a list of clients from Turba? //$clients = diff --git a/lib/Operator.php b/lib/Operator.php index b73b2e2da..9f2da310f 100644 --- a/lib/Operator.php +++ b/lib/Operator.php @@ -2,7 +2,7 @@ /** * Operator Base Class. * - * $Horde: incubator/operator/lib/Operator.php,v 1.3 2008/07/01 22:25:00 bklang Exp $ + * $Horde: incubator/operator/lib/Operator.php,v 1.4 2008/07/03 14:29:16 bklang Exp $ * * Copyright 2008 Alkaloid Networks LLC * @@ -24,8 +24,8 @@ class Operator { require_once 'Horde/Menu.php'; $menu = new Menu(HORDE_MENU_MASK_ALL); - $menu->add(Horde::applicationUrl('search.php'), _("Search"), 'user.png', $registry->getImageDir('horde')); - $menu->add(Horde::applicationUrl('viewgraph.php'), _("View Graphs"), 'user.png', $registry->getImageDir('horde')); + $menu->add(Horde::applicationUrl('viewgraph.php'), _("View Graphs"), 'graphs.png'); + $menu->add(Horde::applicationUrl('search.php'), _("Search"), 'search.png', $registry->getImageDir('horde')); if ($returnType == 'object') { return $menu; diff --git a/search.php b/search.php index e14966f2c..b587fb504 100644 --- a/search.php +++ b/search.php @@ -1,6 +1,6 @@ * @@ -22,28 +22,38 @@ require_once OPERATOR_BASE . '/lib/Form/SearchCDR.php'; $renderer = new Horde_Form_Renderer(); $vars = Variables::getDefaultVariables(); -$form = new SearchCDRForm($vars); +if (!$vars->exists('rowstart')) { + $rowstart = 0; +} elseif (!is_numeric($rowstart = $vars->get('rowstart'))) { + $notification->push(_("Invalid number for row start. Using 0.")); + $rowstart = 0; +} + +$numrows = $prefs->getValue('resultlimit'); +if (!is_numeric($numrows)) { + $notification->push(_("Invalid number for rows for search limit. Using 100.")); + $numrows = 100; +} + +$form = new SearchCDRForm(_("Search CDR Data"), $vars); if ($form->isSubmitted() && $form->validate($vars, true)) { $accountcode = $vars->get('accountcode'); $dcontext = $vars->get('dcontext'); $start = new Horde_Date($vars->get('startdate')); $end = new Horde_Date($vars->get('enddate')); - $data = $operator_driver->getData($start, $end, $accountcode, $dcontext); + $data = $operator_driver->getData($start, $end, $accountcode, $dcontext, + $rowstart, $numrows); $_SESSION['operator']['lastsearch']['params'] = array( 'accountcode' => $vars->get('accountcode'), 'dcontext' => $vars->get('dcontext'), 'startdate' => $vars->get('startdate'), 'enddate' => $vars->get('enddate')); - $_SESSION['operator']['lastsearch']['data'] = $data; } else { if (isset($_SESSION['operator']['lastsearch']['params'])) { foreach($_SESSION['operator']['lastsearch']['params'] as $var => $val) { $vars->set($var, $val); } } - if (isset($_SESSION['operator']['lastsearch']['data'])) { - $data = $_SESSION['operator']['lastsearch']['data']; - } } $title = _("Search Call Detail Records"); @@ -57,6 +67,7 @@ $form->renderActive($renderer, $vars); $columns = unserialize($prefs->getValue('columns')); if (!empty($data)) { require OPERATOR_TEMPLATES . '/search/header.inc'; + unset($data['count'], $data['minutes'], $data['failed']); foreach ($data as $record) { require OPERATOR_TEMPLATES . '/search/row.inc'; } diff --git a/templates/search/header.inc b/templates/search/header.inc index 390cdbb7c..36127b06d 100644 --- a/templates/search/header.inc +++ b/templates/search/header.inc @@ -1,3 +1,10 @@ +Call Statistics Summary:
+
    +
  • Total Calls:
  • +
  • Total Minutes:
  • +
  • Failed Calls:
  • +
+
M&24XAgL~_ex~=p{-sI$*_jz*O^PCsz z!#E(EGXrRK@@R93MrL13EyaaLC=4Lg5D*tfi9#sSrMmqd}342EBsXXjdTV5+^$Kl@3*I zt<1?IAh`kn?=b^_;bqfzS5)T-I9mppUH$_Zn4RLq zBa83f%q*uO+hkn-px3iWUBhj*zEtZ=#J?K1BwoS4fri4we+W?%x_!2UEjG9A57v+ddMu0 zbbp6n;=LcDNq6gD2L9C2J@8#y?*rTbgTj6Ps|^D5|MCj{`@<*H#t`wKg(3XGf2QyU zf0@G{{9_BdAC4aSKNVGeAq>dh`~N>9tN(u{wmT>x9B`-HYmvir?8JeOFVbz5u> zH|V#x^ai*A`gyzm|72hZ`OUy04pZPY)6&ahrsWHdS>_MiW?QUvoolwwWxnYbrv=9G zAbFr`rQinWXqscE(MN|a!$l4~hCDEFhknBjyGi=*G17r<_V)jl zB|4H8rP?#iOLZRs>9-bTIvMExwy4+UuxQe`XV#)U8P$NSZU2ojH2n=T)ZNqrEM0*# zI5i4uc*w#O3aL7Q*+%*5QW{Y@8K%V=Ja7ZFGq?QL&e;54D`OK7Z~U*7wgHIO|JMZJ s)OG(gKsaSB6tDTOk-Qp=;RaBG0e_Hjj63iYg#Z8m07*qoM6N<$g46R|L;wH) literal 0 HcmV?d00001 diff --git a/viewgraph.php b/viewgraph.php index 1a4bea0e9..de820ea4a 100644 --- a/viewgraph.php +++ b/viewgraph.php @@ -1,6 +1,6 @@ * @@ -22,7 +22,7 @@ require_once OPERATOR_BASE . '/lib/Form/SearchCDR.php'; $renderer = new Horde_Form_Renderer(); $vars = Variables::getDefaultVariables(); -$form = new SearchCDRForm($vars); +$form = new SearchCDRForm(_("Graph CDR Data"), $vars); if ($form->isSubmitted() && $form->validate($vars, true)) { $accountcode = $vars->get('accountcode'); $dcontext = $vars->get('dcontext'); @@ -37,11 +37,16 @@ if ($form->isSubmitted() && $form->validate($vars, true)) { if ($stats === false) { $stats = $operator_driver->getMonthlyCallStats($start, $end, $accountcode, $dcontext); - $res = $cache->set($cachekey, serialize($stats), 600); - if ($res === false) { - Horde::logMessage('The cache system has experienced an error. Unable to continue.', __FILE__, __LINE__, PEAR_LOG_ERR); - $notification->push(_("Internal error. Details have been logged for the administrator.")); - unset($stats); + if (is_a($stats, 'PEAR_Error')) { + $notification->push($stats); + $stats = array(); + } else { + $res = $cache->set($cachekey, serialize($stats), 600); + if ($res === false) { + Horde::logMessage('The cache system has experienced an error. Unable to continue.', __FILE__, __LINE__, PEAR_LOG_ERR); + $notification->push(_("Internal error. Details have been logged for the administrator.")); + unset($stats); + } } } else { // Cached data is stored serialized @@ -75,7 +80,6 @@ if (!empty($stats)) { 'graph' => 'failed', 'key' => $cachekey)); } - $title = _("Call Detail Records Graph"); require OPERATOR_TEMPLATES . '/common-header.inc'; -- 2.11.0