<?xml version="1.0"?>
-<!-- $Horde: incubator/operator/config/conf.xml,v 1.2 2008/07/05 14:38:23 bklang Exp $ -->
<configuration>
<configsection name="storage">
<configheader>Storage System Settings</configheader>
<configsection name="menu">
<configheader>Menu Settings</configheader>
+ <configboolean name="export" desc="Should we display an Export
+ link in Operator's menu?">true</configboolean>
<configmultienum name="apps" desc="Select any applications that should be
linked in Operator's menu">
<values>
- <configspecial name="list-horde-apps" />
+ <configspecial name="list-horde-apps"/>
</values>
</configmultienum>
</configsection>
--- /dev/null
+<?php
+/**
+ * Copyright 2008-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * @author Ben Klang <ben@alkaloid.net>
+ */
+
+require_once dirname(__FILE__) . '/lib/Application.php';
+
+$operator = new Operator_Application(array('init' => true));
+$cache = &$GLOBALS['cache'];
+
+require_once OPERATOR_BASE . '/lib/Form/SearchCDR.php';
+
+$renderer = new Horde_Form_Renderer();
+$vars = Horde_Variables::getDefaultVariables();
+$data = array();
+
+if (!$vars->exists('rowstart')) {
+ $rowstart = 0;
+} elseif (!is_numeric($rowstart = $vars->get('rowstart'))) {
+ $notification->push(_("Invalid number for row start. Using 0."));
+ $rowstart = 0;
+}
+
+if (isset($_SESSION['operator']['lastdata'])) {
+ $data = $_SESSION['operator']['lastdata'];
+}
+
+$form = new ExportCDRForm(_("Export Call Detail Records"), $vars);
+if ($form->isSubmitted() && $form->validate($vars, true)) {
+ try {
+ $_SESSION['operator']['lastsearch']['params'] = array(
+ 'accountcode' => $vars->get('accountcode'),
+ 'dcontext' => $vars->get('dcontext'),
+ 'startdate' => $vars->get('startdate'),
+ 'enddate' => $vars->get('enddate'));
+ $_SESSION['operator']['lastdata'] = $data;
+
+ $form->execute();
+
+ } catch (Exception $e) {
+ //$notification->push(_("Invalid date requested."));
+ $notification->push($e);
+ $data = array();
+ }
+} else {
+ if (isset($_SESSION['operator']['lastsearch']['params'])) {
+ foreach($_SESSION['operator']['lastsearch']['params'] as $var => $val) {
+ $vars->set($var, $val);
+ }
+ }
+}
+
+$title = _("Export Call Detail Records");
+
+require OPERATOR_TEMPLATES . '/common-header.inc';
+require OPERATOR_TEMPLATES . '/menu.inc';
+$notification->notify();
+$form->renderActive($renderer, $vars);
+
+$columns = unserialize($prefs->getValue('columns'));
+if (!empty($data)) {
+ require OPERATOR_TEMPLATES . '/search.inc';
+}
+
+require $registry->get('templates', 'horde') . '/common-footer.inc';
* @throws Operator_Exception|Horde_Date_Exception
*/
protected function _getRecords($start, $end, $accountcode = null, $dcontext = null,
- $rowstart = 0, $rowlimit = 100)
+ $rowstart = 0, $rowlimit = null)
{
// Use the query to make the MySQL driver look like the CDR-CSV driver
Horde::logMessage('Invalid start row requested.', __FILE__, __LINE__, PEAR_LOG_ERR);
throw new Operator_Exception(_("Internal error. Details have been logged for the administrator."));
}
- if (!is_numeric($rowlimit)) {
+ if (!is_null($rowlimit) && !is_numeric($rowlimit)) {
Horde::logMessage('Invalid row limit requested.', __FILE__, __LINE__, PEAR_LOG_ERR);
throw new Operator_Exception(_("Internal error. Details have been logged for the administrator."));
}
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_null($rowlimit)) {
+ $res = $this->_db->query($sql, $values);
+ } else {
+ $res = $this->_db->limitQuery($sql, $rowstart, $rowlimit, $values);
+ }
if (is_a($res, 'PEAR_Error')) {
Horde::logMessage($res, __FILE__, __LINE__, PEAR_LOG_ERR);
throw new Operator_Exception(_("Internal error. Details have been logged for the administrator."));
public function __construct($title, &$vars)
{
- parent::Horde_Form($vars, $title);
+ parent::__construct($vars, $title);
// FIXME: Generate a list of clients from Turba?
//$clients =
$params = array($start_year, $end_year, $picker, $format_in,
$format_out, $show_seconds);
- $this->addVariable(_("Account Code"), 'accountcode', 'enum', false, false, null, array($accountcodes));
- $this->addVariable(_("Destination Context"), 'dcontext', 'text', false, false, _("An empty destination context will match all destination contexts."));
- $this->addVariable(_("Start Date & Time"), 'startdate', 'datetime', true, false, null, $params);
- $this->addVariable(_("End Date & Time"), 'enddate', 'datetime', true, false, null, $params);
+ $this->addVariable(_("Account Code"), 'accountcode', 'enum', false,
+ false, null, array($accountcodes));
+ $this->addVariable(_("Destination Context"), 'dcontext', 'text', false,
+ false, _("An empty destination context will match all destination contexts."));
+ $this->addVariable(_("Start Date & Time"), 'startdate', 'datetime',
+ true, false, null, $params);
+ $this->addVariable(_("End Date & Time"), 'enddate', 'datetime', true,
+ false, null, $params);
+ }
+}
+
+class ExportCDRForm extends SearchCDRForm
+{
+ public function __construct($title, &$vars)
+ {
+ parent::__construct($title, $vars);
+
+ $formats = array(
+ Horde_Data::EXPORT_CSV => 'Comma-Delimited (CSV)',
+ Horde_Data::EXPORT_TSV => 'Tab-Delimited',
+ );
+
+ $this->addVariable(_("Data Format"), 'format', 'enum', true, false,
+ null, array($formats));
+ }
+
+ public function execute()
+ {
+ global $operator;
+ if (empty($operator) || empty($operator->driver)) {
+ $operator = new Operator_Application(array('init' => true));
+ }
+
+ $start = new Horde_Date($this->_vars->get('startdate'));
+ $end = new Horde_Date($this->_vars->get('enddate'));
+ $accountcode = $this->_vars->get('accountcode');
+ $dcontects = $this->_vars->get('dcontext');
+ if (empty($dcontext)) {
+ $dcontext = '%';
+ }
+ list($stats, $data) = $operator->driver->getRecords($start, $end,
+ $accountcode,
+ $dcontext, 0,
+ null);
+ switch($this->_vars->get('format')) {
+ case Horde_Data::EXPORT_CSV:
+ $ext = 'csv';
+ $fmt = Horde_Data::singleton('csv');
+ break;
+
+ case Horde_Data::EXPORT_TSV:
+ $ext = 'tsv';
+ $fmt = Horde_Data::singleton('tsv');
+ break;
+
+ default:
+ throw new Operator_Exception(_("Invalid data format requested."));
+ break;
+ }
+
+ $filename = 'export-' . uniqid() . '.' . $ext;
+ $fmt->exportFile($filename, $data, true);
+ exit;
}
}
/**
* Operator Base Class.
*
- * $Horde: incubator/operator/lib/Operator.php,v 1.18 2009/12/01 12:52:49 jan Exp $
- *
* Copyright 2008-2010 The Horde Project (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (GPL). If you
/**
* Build Operator's list of menu items.
*/
- function getMenu($returnType = 'object')
+ public static function getMenu($returnType = 'object')
{
global $conf, $registry, $browser, $print_link;
$menu = new Horde_Menu(Horde_Menu::MASK_ALL);
- $menu->add(Horde::applicationUrl('viewgraph.php'), _("View Graphs"), 'graphs.png', null, null, null, basename($_SERVER['PHP_SELF']) == 'index.php' ? 'current' : null);
- $menu->add(Horde::applicationUrl('search.php'), _("Search"), 'search.png', $registry->getImageDir('horde'));
+ $menu->add(Horde::applicationUrl('viewgraph.php'), _("_View Graphs"), 'graphs.png', null, null, null, basename($_SERVER['PHP_SELF']) == 'index.php' ? 'current' : null);
+ $menu->add(Horde::applicationUrl('search.php'), _("_Search"), 'search.png', $registry->getImageDir('horde'));
+
+ /* Export */
+ if ($GLOBALS['conf']['menu']['export']) {
+ $menu->add(Horde::applicationUrl('export.php'), _("_Export"), 'data.png', $GLOBALS['registry']->getImageDir('horde'));
+ }
if ($returnType == 'object') {
return $menu;
}
}
- function getColumns()
+ public static function getColumns()
{
#static $columns = array(
$columns = array(
}
- function getColumnName($column)
+ public static function getColumnName($column)
{
$columns = Operator::getColumns();
return $columns[$column];
}
- function getAMAFlagName($flagid)
+ public static function getAMAFlagName($flagid)
{
// See <asterisk/cdr.h> for definitions
switch($flagid) {
*
* @return array List of valid account codes.
*/
- function getAccountCodes($permfilter = false)
+ public static function getAccountCodes($permfilter = false)
{
global $operator;
if (empty($operator) || empty($operator->driver)) {
$operator = new Operator_Application(array('init' => true));
}
-
+
// Set up arrays for filtering
$keys = $values = $operator->driver->getAccountCodes();
return $accountcodes;
}
- function getGraphInfo($graphid)
+ public static function getGraphInfo($graphid = null)
{
- switch($graphid) {
- case 'numcalls':
- return array(
- 'title' => _("Number of Calls by Month"),
- 'axisX' => _("Month"),
- 'axisY' => _("Number of Calls"),
- );
- break;
- case 'minutes':
- return array(
- 'title' => _("Total Minutes Used by Month"),
- 'axisX' => _("Month"),
- 'axisY' => _("Minute"),
- 'numberformat' => '%0.1f',
- );
- break;
- case 'failed':
- return array(
- 'title' => _("Number of Failed Calls by Month"),
- 'axisX' => _("Month"),
- 'axisY' => _("Failed Calls"),
- );
- break;
- }
+ static $graphs;
+
+ if (empty($graphs)) {
+ $graphs = array(
+ 'numcalls' => array(
+ 'title' => _("Number of Calls by Month"),
+ 'axisX' => _("Month"),
+ 'axisY' => _("Number of Calls"),
+ ),
+ 'minutes' => array(
+ 'title' => _("Total Minutes Used by Month"),
+ 'axisX' => _("Month"),
+ 'axisY' => _("Minute"),
+ 'numberformat' => '%0.1f',
+ ),
+
+ 'failed' => array(
+ 'title' => _("Number of Failed Calls by Month"),
+ 'axisX' => _("Month"),
+ 'axisY' => _("Failed Calls"),
+ ),
+ );
+ }
+
+ if ($graphid === null) {
+ return $graphs;
+ }
+
+ if (isset($graphs[$graphid])) {
+ return $graphs[$graphid];
+ } else {
+ throw new Operator_Exception(_("Invalid graph type."));
+ }
}
}