/**
* Fetch time slices with optional filter.
*
* @param array $filters An array of properties to filter on. Each entry
* is a field => value format. Possible field values:
* client, jobtype, submitted, exported, billable,
* start, end, employee, id, costobject.
* @param array $fields
*
* @return array Array of timeslice objects
*/
public function getHours(array $filters = array(), array $fields = array())
{
global $conf;
$fieldlist = array('id' => 'b.timeslice_id as id', 'client' => ' b.clientjob_id as client', 'employee' => ' b.employee_id as employee', 'type' => ' b.jobtype_id as type', '_type_name' => ' j.jobtype_name as "_type_name"', 'hours' => ' b.timeslice_hours as hours', 'rate' => ' b.timeslice_rate as rate', 'billable' => empty($conf['time']['choose_ifbillable']) ? ' j.jobtype_billable as billable' : ' b.timeslice_isbillable as billable', 'date' => ' b.timeslice_date as "date"', 'description' => ' b.timeslice_description as description', 'note' => ' b.timeslice_note as note', 'submitted' => ' b.timeslice_submitted as submitted', 'costobject' => ' b.costobject_id as costobject');
if (!empty($fields)) {
$fieldlist = array_keys(array_intersect(array_flip($fieldlist), $fields));
}
$fieldlist = implode(', ', $fieldlist);
$sql = 'SELECT ' . $fieldlist . ' FROM hermes_timeslices b INNER JOIN hermes_jobtypes j ON b.jobtype_id = j.jobtype_id';
if (count($filters) > 0) {
$where = '';
$glue = '';
foreach ($filters as $field => $filter) {
switch ($field) {
case 'client':
$where .= $glue . $this->_equalClause('b.clientjob_id', $filter);
$glue = ' AND';
break;
case 'jobtype':
$where .= $glue . $this->_equalClause('b.jobtype_id', $filter);
$glue = ' AND';
break;
case 'submitted':
$where .= $glue . ' timeslice_submitted = ' . (int) $filter;
$glue = ' AND';
break;
case 'exported':
$where .= $glue . ' timeslice_exported = ' . (int) $filter;
$glue = ' AND';
break;
case 'billable':
$where .= $glue . (empty($conf['time']['choose_ifbillable']) ? ' jobtype_billable = ' : ' timeslice_isbillable = ') . (int) $filter;
$glue = ' AND';
break;
case 'start':
$where .= $glue . ' timeslice_date >= ' . (int) $filter;
$glue = ' AND';
break;
case 'end':
$where .= $glue . ' timeslice_date <= ' . (int) $filter;
$glue = ' AND';
break;
case 'employee':
$where .= $glue . $this->_equalClause('employee_id', $filter);
$glue = ' AND';
break;
case 'id':
if (is_array($filter)) {
foreach ($filter as &$id) {
$id = (int) $id;
}
}
$where .= $glue . $this->_equalClause('timeslice_id', $filter, false);
$glue = ' AND';
break;
case 'costobject':
$where .= $glue . $this->_equalClause('costobject_id', $filter);
$glue = ' AND';
break;
}
}
}
if (!empty($where)) {
$sql .= ' WHERE ' . $where;
}
$sql .= ' ORDER BY timeslice_date DESC, clientjob_id';
try {
$hours = $this->_db->selectAll($sql);
} catch (Horde_Db_Exception $e) {
throw new Hermes_Exception($e);
}
$slices = array();
// Do per-record processing
$addcostobject = empty($fields) || in_array('costobject', $fields);
foreach ($hours as $key => $hour) {
if (isset($hour['date'])) {
// Convert timestamps to Horde_Date objects
$hour['date'] = new Horde_Date($hour['date']);
}
if (isset($hour['description'])) {
$hour['description'] = $this->_convertFromDriver($hour['description']);
}
if (isset($hour['note'])) {
$hour['note'] = $this->_convertFromDriver($hour['note']);
}
if ($addcostobject) {
if (empty($hour['costobject'])) {
$hour['_costobject_name'] = '';
} else {
try {
$costobject = Hermes::getCostObjectByID($hour['costobject']);
$hour['_costobject_name'] = $costobject['name'];
} catch (Horde_Exception $e) {
$hour['_costobject_name'] = sprintf(_("Error: %s"), $e->getMessage());
}
}
}
$slices[$key] = new Hermes_Slice($hour);
}
return $slices;
}