From: Michael J Rubinsky Date: Thu, 13 Jan 2011 17:28:43 +0000 (-0500) Subject: H4 style filename X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=541b169013331f2021eb82d8e818cb7b2c5528d4;p=horde.git H4 style filename --- diff --git a/hermes/lib/Driver/Sql.php b/hermes/lib/Driver/Sql.php new file mode 100644 index 000000000..803a4d17a --- /dev/null +++ b/hermes/lib/Driver/Sql.php @@ -0,0 +1,683 @@ + + * @author Michael J. Rubinsky + * @package Hermes + */ +class Hermes_Driver_Sql extends Hermes_Driver +{ + /** + * Handle for the current database connection. + * + * @var Horde_Db_Adapter + */ + protected $_db; + + /** + * Constructor + * + * @param array $params A hash containing connection parameters. + *
+     *   db_adapter => The Horde_Db_Adapter object
+     * 
+ * + * @return Hermes_Driver_Sql The driver object. + */ + public function __construct($params = array()) + { + parent::__construct($params); + if (empty($params['db_adapter'])) { + throw new InvalidArgumentException('Missing Horde_Db_Adapter parameter.'); + } + $this->_db = $params['db_adapter']; + } + + /** + * Save a row of billing information. + * + * @param string $employee The Horde ID of the person who worked the + * hours. + * @param array $entries The billing information to enter. Each array + * row must contain the following entries: + * 'date' The day the hours were worked (ISO format) + * 'client' The id of the client the work was done for. + * 'type' The type of work done. + * 'hours' The number of hours worked + * 'rate' The hourly rate the work was done at. + * 'billable' (optional) Whether or not the work is + * billable hours. + * 'description' A short description of the work. + * + * @return integer The new timeslice_id of the newly entered slice + * @throws Hermes_Exception + */ + public function enterTime($employee, array $info) + { + /* Get job rate */ + $sql = 'SELECT jobtype_rate FROM hermes_jobtypes WHERE jobtype_id = ?'; + try { + $job_rate = $this->_db->selectValue($sql, array($info['type'])); + } catch (Horde_Db_Exception $e) { + throw new Hermes_Exception($e); + } + $dt = new Date($info['date']); + $sql = 'INSERT INTO hermes_timeslices (' . + 'clientjob_id, employee_id, jobtype_id, ' . + 'timeslice_hours, timeslice_isbillable, ' . + 'timeslice_date, timeslice_description, ' . + 'timeslice_note, timeslice_rate, costobject_id) ' . + 'VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'; + + $values = array($info['client'], + $employee, + $info['type'], + $info['hours'], + isset($info['billable']) ? (int)$info['billable'] : 0, + (int)$dt->getTime(DATE_FORMAT_UNIXTIME) + 1, + $info['description'], + $info['note'], + (float)$job_rate, + (empty($info['costobject']) ? null : + $info['costobject'])); + + try { + return $this->_db->insert($sql, $values); + } catch (Horde_Db_Exception $e) { + throw new Hermes_Exception($e); + } + } + + /** + * Update a set of billing information. + * + * @param array $entries The billing information to enter. Each array row + * must contain the following entries: + * 'id' The id of this time entry. + * 'date' The day the hours were worked (ISO format) + * 'client' The id of the client the work was done for. + * 'type' The type of work done. + * 'hours' The number of hours worked + * 'rate' The hourly rate the work was done at. + * 'billable' Whether or not the work is billable hours. + * 'description' A short description of the work. + * + * If any rows contain a 'delete' entry, those rows + * will be deleted instead of updated. + * + * @return mixed boolean + * @throws Horde_Exception_PermissionDenied + * @throws Hermes_Exception + */ + public function updateTime($entries) + { + foreach ($entries as $info) { + if (!Hermes::canEditTimeslice($info['id'])) { + throw new Horde_Exception_PermissionDenied(_("Access denied; user cannot modify this timeslice.")); + } + if (!empty($info['delete'])) { + try { + return $this->_db->delete('DELETE FROM hermes_timeslices WHERE timeslice_id = ?', array((int)$info['id'])); + } catch (Horde_Db_Exception $e) { + throw new Hermes_Exception($e); + } + } else { + if (isset($info['employee'])) { + $employee_cl = ' employee_id = ?,'; + + $values = array($info['employee']); + } else { + $employee_cl = ''; + } + $dt = new Date($info['date']); + $sql = 'UPDATE hermes_timeslices SET' . $employee_cl . + ' clientjob_id = ?, jobtype_id = ?,' . + ' timeslice_hours = ?, timeslice_isbillable = ?,' . + ' timeslice_date = ?, timeslice_description = ?,' . + ' timeslice_note = ?, costobject_id = ?' . + ' WHERE timeslice_id = ?'; + $values = array($info['client'], + $info['type'], + $info['hours'], + (isset($info['billable']) ? (int)$info['billable'] : 0), + (int)$dt->getTime(DATE_FORMAT_UNIXTIME) + 1, + $info['description'], + $info['note'], + (empty($info['costobject']) ? null : $info['costobject']), + (int)$info['id']); + try { + return $this->_db->update($sql, $values); + } catch (Horde_Db_Exception $e) { + throw new Hermes_Exception($e); + } + } + } + } + + /** + * @TODO + * + * @global $conf + * @param $filters + * @param $fields + * @return + */ + 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': + $where .= $glue . $this->_equalClause('timeslice_id', + (int)$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); + } + + // Do per-record processing + foreach (array_keys($hours) as $hkey) { + // Convert timestamps to Horde_Date objects + $hours[$hkey]['date'] = new Horde_Date($hours[$hkey]['date']); + + // Add cost object names to the results. + if (empty($fields) || in_array('costobject', $fields)) { + if (empty($hours[$hkey]['costobject'])) { + $hours[$hkey]['_costobject_name'] = ''; + } else { + try { + $costobject = Hermes::getCostObjectByID($hours[$hkey]['costobject']); + } catch (Horde_Exception $e) { + $hours[$hkey]['_costobject_name'] = sprintf(_("Error: %s"), $e->getMessage()); + } + $hours[$hkey]['_costobject_name'] = $costobject['name']; + } + } + } + + return $hours; + } + + /** + * @TODO + */ + private function _equalClause($lhs, $rhs, $quote = true) + { + require_once 'Horde/SQL.php'; + + if (!is_array($rhs)) { + if ($quote) { + return sprintf(' %s = %s', $lhs, $this->_db->quote($rhs)); + } + return sprintf(' %s = %s', $lhs, $rhs); + } + + if (count($rhs) == 0) { + return ' FALSE'; + } + + $glue = ''; + $ret = sprintf(' %s IN ( ', $lhs); + foreach ($rhs as $value) { + $ret .= $glue . $this->_db->quote($value); + $glue = ', '; + } + return $ret . ' )'; + } + + /** + * @TODO + * + * @param $field + * @param $hours + * @return + */ + public function markAs($field, $hours) + { + if (!count($hours)) { + return false; + } + + switch ($field) { + case 'submitted': + $h_field = 'timeslice_submitted'; + break; + + case 'exported': + $h_field = 'timeslice_exported'; + break; + + default: + return false; + } + + $ids = array(); + foreach ($hours as $entry) { + $ids[] = (int)$entry['id']; + } + + $sql = 'UPDATE hermes_timeslices SET ' . $h_field . ' = 1' . + ' WHERE timeslice_id IN (' . implode(',', $ids) . ')'; + + return $this->_db->update($sql); + } + + /** + * @TODO + * + * @param $criteria + * @return + */ + public function listJobTypes(array $criteria = array()) + { + $where = array(); + $values = array(); + if (isset($criteria['id'])) { + $where[] = 'jobtype_id = ?'; + $values[] = $criteria['id']; + } + if (isset($criteria['enabled'])) { + $where[] = 'jobtype_enabled = ?'; + $values[] = ($criteria['enabled'] ? 1 : 0); + } + + $sql = 'SELECT jobtype_id, jobtype_name, jobtype_enabled' . + ', jobtype_rate, jobtype_billable FROM hermes_jobtypes' . + (empty($where) ? '' : (' WHERE ' . join(' AND ', $where))) . + ' ORDER BY jobtype_name'; + + try { + $rows = $this->_db->selectAll($sql, $values); + } catch (Horde_Db_Exception $e) { + throw new Hermes_Exception($e); + } + + $results = array(); + foreach ($rows as $row) { + $id = $row['jobtype_id']; + $results[$id] = array('id' => $id, + 'name' => $row['jobtype_name'], + 'rate' => (float)$row['jobtype_rate'], + 'billable' => (int)$row['jobtype_billable'], + 'enabled' => !empty($row['jobtype_enabled'])); + } + + return $results; + } + + public function updateJobType($jobtype) + { + if (!isset($jobtype['enabled'])) { + $jobtype['enabled'] = 1; + } + if (!isset($jobtype['billable'])) { + $jobtype['billable'] = 1; + } + if (empty($jobtype['id'])) { + $sql = 'INSERT INTO hermes_jobtypes (jobtype_name, jobtype_enabled, ' + . 'jobtype_rate, jobtype_billable) VALUES (?, ?, ?, ?)'; + $values = array($jobtype['name'], + (int)$jobtype['enabled'], + (float)$jobtype['rate'], + (int)$jobtype['billable']); + + try { + return $this->_db->insert($sql, $values); + } catch (Horde_Db_Exception $e) { + throw new Hermes_Exception($e); + } + } else { + $sql = 'UPDATE hermes_jobtypes' . + ' SET jobtype_name = ?, jobtype_enabled = ?, jobtype_rate = ?,' . + ' jobtype_billable = ? WHERE jobtype_id = ?'; + $values = array($jobtype['name'], + (int)$jobtype['enabled'], + (float)$jobtype['rate'], + (int)$jobtype['billable'], + $jobtype['id']); + + try { + $this->_db->update($sql, $values); + } catch (Horde_Db_Exception $e) { + throw new Hermes_Exception($e); + } + + return $jobtype['id']; + } + } + + public function deleteJobType($jobTypeID) + { + try { + return $this->_db->delete('DELETE FROM hermes_jobtypes WHERE jobtype_id = ?', array($jobTypeID)); + } catch (Horde_Db_Exception $e) { + throw Hermes_Exception($e); + } + } + + /** + * @see Hermes_Driver::updateDeliverable + */ + public function updateDeliverable($deliverable) + { + if (empty($deliverable['id'])) { + $sql = 'INSERT INTO hermes_deliverables (' . + ' client_id, deliverable_name, deliverable_parent,' . + ' deliverable_estimate, deliverable_active,' . + ' deliverable_description) VALUES (?, ?, ?, ?, ?, ?)'; + $values = array($deliverable['client_id'], + $deliverable['name'], + (empty($deliverable['parent']) ? null : + (int)$deliverable['parent']), + (empty($deliverable['estimate']) ? null : + $deliverable['estimate']), + ($deliverable['active'] ? 1 : 0), + (empty($deliverable['description']) ? null : + $deliverable['description'])); + + try { + return $this->_db->insert($sql, $values); + } catch (Horde_Db_Exception $e) { + throw new Hermes_Exception($e); + } + } else { + $sql = 'UPDATE hermes_deliverables SET client_id = ?,' . + ' deliverable_name = ?, deliverable_parent = ?,' . + ' deliverable_estimate = ?, deliverable_active = ?,' . + ' deliverable_description = ? WHERE deliverable_id = ?'; + $values = array($deliverable['client_id'], + $deliverable['name'], + (empty($deliverable['parent']) ? null : + (int)$deliverable['parent']), + (empty($deliverable['estimate']) ? null : + $deliverable['estimate']), + ($deliverable['active'] ? 1 : 0), + (empty($deliverable['description']) ? null : + $deliverable['description']), + $deliverable['id']); + try { + $this->_db->update($sql, $values); + return $deliverable['id']; + } catch (Horde_Db_Exception $e) { + throw new Hermes_Exception($e); + } + } + } + + /** + * @see Hermes_Driver::listDeliverables() + */ + public function listDeliverables($criteria = array()) + { + $where = array(); + $values = array(); + if (isset($criteria['id'])) { + $where[] = 'deliverable_id = ?'; + $values[] = $criteria['id']; + } + if (isset($criteria['client_id'])) { + $where[] = 'client_id = ?'; + $values[] = $criteria['client_id']; + } + if (isset($criteria['active'])) { + if ($criteria['active']) { + $where[] = 'deliverable_active <> ?'; + } else { + $where[] = 'deliverable_active = ?'; + } + $values[] = 0; + } + + $sql = 'SELECT * FROM hermes_deliverables' . + (count($where) ? ' WHERE ' . join(' AND ', $where) : ''); + + try { + $rows = $this->_db->selectAll($sql, $values); + } catch (Horde_Db_Exception $e) { + throw new Hermes_Exception($e); + } + + $deliverables = array(); + foreach ($rows as $row) { + $deliverable = array('id' => $row['deliverable_id'], + 'client_id' => $row['client_id'], + 'name' => $row['deliverable_name'], + 'parent' => $row['deliverable_parent'], + 'estimate' => $row['deliverable_estimate'], + 'active' => !empty($row['deliverable_active']), + 'description' => $row['deliverable_description']); + $deliverables[$row['deliverable_id']] = $deliverable; + } + + return $deliverables; + } + + /** + * @see Hermes_Driver::updateDeliverable + * @throws Hermes_Exception + */ + public function deleteDeliverable($deliverableID) + { + $sql = 'SELECT COUNT(*) AS c FROM hermes_deliverables WHERE deliverable_parent = ?'; + $values = array($deliverableID); + + try { + $result = $this->_db->selectValue($sql, $values); + } catch (Horde_Db_Exception $e) { + throw new Hermes_Exception($e); + } + if (!empty($result)) { + throw new Hermes_Exception(_("Cannot delete deliverable; it has children.")); + } + + $sql = 'SELECT COUNT(*) AS c FROM hermes_timeslices WHERE costobject_id = ?'; + $values = array($deliverableID); + try { + $result = $this->_db->selectValue($sql, $values); + } catch (Horde_Db_Exception $e) { + throw new Hermes_Exception($e); + } + if (!empty($result)) { + throw Hermes_Exception(_("Cannot delete deliverable; there is time entered on it.")); + } + + $sql = 'DELETE FROM hermes_deliverables WHERE deliverable_id = ?'; + $values = array($deliverableID); + + try { + return $this->_db->delete($sql, $values); + } catch (Horde_Db_Exception $e) { + throw new Hermes_Exception($e); + } + } + + public function getClientSettings($clientID) + { + $clients = Hermes::listClients(); + if (empty($clientID) || !isset($clients[$clientID])) { + throw new Hermes_Exception('Does not exist'); + } + + $sql = 'SELECT clientjob_id, clientjob_enterdescription,' . + ' clientjob_exportid FROM hermes_clientjobs' . + ' WHERE clientjob_id = ?'; + $values = array($clientID); + + try { + $rows = $this->_db->selectAll($sql, $values); + } catch (Horde_Db_Exception $e) { + throw new Hermes_Exception($e); + } + $clientJob = array(); + foreach ($rows as $row) { + $clientJob[$row['clientjob_id']] = array($row['clientjob_enterdescription'], $row['clientjob_exportid']); + } + + if (isset($clientJob[$clientID])) { + $settings = array('id' => $clientID, + 'enterdescription' => $clientJob[$clientID][0], + 'exportid' => $clientJob[$clientID][1]); + } else { + $settings = array('id' => $clientID, + 'enterdescription' => 1, + 'exportid' => null); + } + + $settings['name'] = $clients[$clientID]; + return $settings; + } + + /** + * @TODO + * + * @param $clientID + * @param $enterdescription + * @param string $exportid + * @return + */ + public function updateClientSettings($clientID, $enterdescription = 1, $exportid = null) + { + if (empty($exportid)) { + $exportid = null; + } + + $sql = 'SELECT clientjob_id FROM hermes_clientjobs WHERE clientjob_id = ?'; + $values = array($clientID); + + if ($this->_db->selectValue($sql, $values) !== $clientID) { + $sql = 'INSERT INTO hermes_clientjobs (clientjob_id,' . + ' clientjob_enterdescription, clientjob_exportid)' . + ' VALUES (?, ?, ?)'; + $values = array($clientID, (int)$enterdescription, $exportid); + + try { + return $this->_db->insert($sql, $values); + } catch (Horde_Db_Exception $e) { + throw new Hermes_Exception($e); + } + } else { + $sql = 'UPDATE hermes_clientjobs SET' . + ' clientjob_exportid = ?, clientjob_enterdescription = ?' . + ' WHERE clientjob_id = ?'; + $values = array($exportid, (int)$enterdescription, $clientID); + + try { + return $this->_db->update($sql, $values); + } catch (Horde_Db_Exception $e) { + throw new Hermes_Exception($e); + } + } + } + + /** + * @TODO + * @global $conf + * @return + */ + public function purge() + { + global $conf; + + $query = 'DELETE FROM hermes_timeslices' . + ' WHERE timeslice_exported = ? AND timeslice_date < ?'; + $values = array(1, mktime(0, 0, 0, date('n'), + date('j') - $conf['time']['days_to_keep'])); + return $this->_db->delete($query, $values); + } + +} diff --git a/hermes/lib/Driver/sql.php b/hermes/lib/Driver/sql.php deleted file mode 100644 index 803a4d17a..000000000 --- a/hermes/lib/Driver/sql.php +++ /dev/null @@ -1,683 +0,0 @@ - - * @author Michael J. Rubinsky - * @package Hermes - */ -class Hermes_Driver_Sql extends Hermes_Driver -{ - /** - * Handle for the current database connection. - * - * @var Horde_Db_Adapter - */ - protected $_db; - - /** - * Constructor - * - * @param array $params A hash containing connection parameters. - *
-     *   db_adapter => The Horde_Db_Adapter object
-     * 
- * - * @return Hermes_Driver_Sql The driver object. - */ - public function __construct($params = array()) - { - parent::__construct($params); - if (empty($params['db_adapter'])) { - throw new InvalidArgumentException('Missing Horde_Db_Adapter parameter.'); - } - $this->_db = $params['db_adapter']; - } - - /** - * Save a row of billing information. - * - * @param string $employee The Horde ID of the person who worked the - * hours. - * @param array $entries The billing information to enter. Each array - * row must contain the following entries: - * 'date' The day the hours were worked (ISO format) - * 'client' The id of the client the work was done for. - * 'type' The type of work done. - * 'hours' The number of hours worked - * 'rate' The hourly rate the work was done at. - * 'billable' (optional) Whether or not the work is - * billable hours. - * 'description' A short description of the work. - * - * @return integer The new timeslice_id of the newly entered slice - * @throws Hermes_Exception - */ - public function enterTime($employee, array $info) - { - /* Get job rate */ - $sql = 'SELECT jobtype_rate FROM hermes_jobtypes WHERE jobtype_id = ?'; - try { - $job_rate = $this->_db->selectValue($sql, array($info['type'])); - } catch (Horde_Db_Exception $e) { - throw new Hermes_Exception($e); - } - $dt = new Date($info['date']); - $sql = 'INSERT INTO hermes_timeslices (' . - 'clientjob_id, employee_id, jobtype_id, ' . - 'timeslice_hours, timeslice_isbillable, ' . - 'timeslice_date, timeslice_description, ' . - 'timeslice_note, timeslice_rate, costobject_id) ' . - 'VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'; - - $values = array($info['client'], - $employee, - $info['type'], - $info['hours'], - isset($info['billable']) ? (int)$info['billable'] : 0, - (int)$dt->getTime(DATE_FORMAT_UNIXTIME) + 1, - $info['description'], - $info['note'], - (float)$job_rate, - (empty($info['costobject']) ? null : - $info['costobject'])); - - try { - return $this->_db->insert($sql, $values); - } catch (Horde_Db_Exception $e) { - throw new Hermes_Exception($e); - } - } - - /** - * Update a set of billing information. - * - * @param array $entries The billing information to enter. Each array row - * must contain the following entries: - * 'id' The id of this time entry. - * 'date' The day the hours were worked (ISO format) - * 'client' The id of the client the work was done for. - * 'type' The type of work done. - * 'hours' The number of hours worked - * 'rate' The hourly rate the work was done at. - * 'billable' Whether or not the work is billable hours. - * 'description' A short description of the work. - * - * If any rows contain a 'delete' entry, those rows - * will be deleted instead of updated. - * - * @return mixed boolean - * @throws Horde_Exception_PermissionDenied - * @throws Hermes_Exception - */ - public function updateTime($entries) - { - foreach ($entries as $info) { - if (!Hermes::canEditTimeslice($info['id'])) { - throw new Horde_Exception_PermissionDenied(_("Access denied; user cannot modify this timeslice.")); - } - if (!empty($info['delete'])) { - try { - return $this->_db->delete('DELETE FROM hermes_timeslices WHERE timeslice_id = ?', array((int)$info['id'])); - } catch (Horde_Db_Exception $e) { - throw new Hermes_Exception($e); - } - } else { - if (isset($info['employee'])) { - $employee_cl = ' employee_id = ?,'; - - $values = array($info['employee']); - } else { - $employee_cl = ''; - } - $dt = new Date($info['date']); - $sql = 'UPDATE hermes_timeslices SET' . $employee_cl . - ' clientjob_id = ?, jobtype_id = ?,' . - ' timeslice_hours = ?, timeslice_isbillable = ?,' . - ' timeslice_date = ?, timeslice_description = ?,' . - ' timeslice_note = ?, costobject_id = ?' . - ' WHERE timeslice_id = ?'; - $values = array($info['client'], - $info['type'], - $info['hours'], - (isset($info['billable']) ? (int)$info['billable'] : 0), - (int)$dt->getTime(DATE_FORMAT_UNIXTIME) + 1, - $info['description'], - $info['note'], - (empty($info['costobject']) ? null : $info['costobject']), - (int)$info['id']); - try { - return $this->_db->update($sql, $values); - } catch (Horde_Db_Exception $e) { - throw new Hermes_Exception($e); - } - } - } - } - - /** - * @TODO - * - * @global $conf - * @param $filters - * @param $fields - * @return - */ - 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': - $where .= $glue . $this->_equalClause('timeslice_id', - (int)$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); - } - - // Do per-record processing - foreach (array_keys($hours) as $hkey) { - // Convert timestamps to Horde_Date objects - $hours[$hkey]['date'] = new Horde_Date($hours[$hkey]['date']); - - // Add cost object names to the results. - if (empty($fields) || in_array('costobject', $fields)) { - if (empty($hours[$hkey]['costobject'])) { - $hours[$hkey]['_costobject_name'] = ''; - } else { - try { - $costobject = Hermes::getCostObjectByID($hours[$hkey]['costobject']); - } catch (Horde_Exception $e) { - $hours[$hkey]['_costobject_name'] = sprintf(_("Error: %s"), $e->getMessage()); - } - $hours[$hkey]['_costobject_name'] = $costobject['name']; - } - } - } - - return $hours; - } - - /** - * @TODO - */ - private function _equalClause($lhs, $rhs, $quote = true) - { - require_once 'Horde/SQL.php'; - - if (!is_array($rhs)) { - if ($quote) { - return sprintf(' %s = %s', $lhs, $this->_db->quote($rhs)); - } - return sprintf(' %s = %s', $lhs, $rhs); - } - - if (count($rhs) == 0) { - return ' FALSE'; - } - - $glue = ''; - $ret = sprintf(' %s IN ( ', $lhs); - foreach ($rhs as $value) { - $ret .= $glue . $this->_db->quote($value); - $glue = ', '; - } - return $ret . ' )'; - } - - /** - * @TODO - * - * @param $field - * @param $hours - * @return - */ - public function markAs($field, $hours) - { - if (!count($hours)) { - return false; - } - - switch ($field) { - case 'submitted': - $h_field = 'timeslice_submitted'; - break; - - case 'exported': - $h_field = 'timeslice_exported'; - break; - - default: - return false; - } - - $ids = array(); - foreach ($hours as $entry) { - $ids[] = (int)$entry['id']; - } - - $sql = 'UPDATE hermes_timeslices SET ' . $h_field . ' = 1' . - ' WHERE timeslice_id IN (' . implode(',', $ids) . ')'; - - return $this->_db->update($sql); - } - - /** - * @TODO - * - * @param $criteria - * @return - */ - public function listJobTypes(array $criteria = array()) - { - $where = array(); - $values = array(); - if (isset($criteria['id'])) { - $where[] = 'jobtype_id = ?'; - $values[] = $criteria['id']; - } - if (isset($criteria['enabled'])) { - $where[] = 'jobtype_enabled = ?'; - $values[] = ($criteria['enabled'] ? 1 : 0); - } - - $sql = 'SELECT jobtype_id, jobtype_name, jobtype_enabled' . - ', jobtype_rate, jobtype_billable FROM hermes_jobtypes' . - (empty($where) ? '' : (' WHERE ' . join(' AND ', $where))) . - ' ORDER BY jobtype_name'; - - try { - $rows = $this->_db->selectAll($sql, $values); - } catch (Horde_Db_Exception $e) { - throw new Hermes_Exception($e); - } - - $results = array(); - foreach ($rows as $row) { - $id = $row['jobtype_id']; - $results[$id] = array('id' => $id, - 'name' => $row['jobtype_name'], - 'rate' => (float)$row['jobtype_rate'], - 'billable' => (int)$row['jobtype_billable'], - 'enabled' => !empty($row['jobtype_enabled'])); - } - - return $results; - } - - public function updateJobType($jobtype) - { - if (!isset($jobtype['enabled'])) { - $jobtype['enabled'] = 1; - } - if (!isset($jobtype['billable'])) { - $jobtype['billable'] = 1; - } - if (empty($jobtype['id'])) { - $sql = 'INSERT INTO hermes_jobtypes (jobtype_name, jobtype_enabled, ' - . 'jobtype_rate, jobtype_billable) VALUES (?, ?, ?, ?)'; - $values = array($jobtype['name'], - (int)$jobtype['enabled'], - (float)$jobtype['rate'], - (int)$jobtype['billable']); - - try { - return $this->_db->insert($sql, $values); - } catch (Horde_Db_Exception $e) { - throw new Hermes_Exception($e); - } - } else { - $sql = 'UPDATE hermes_jobtypes' . - ' SET jobtype_name = ?, jobtype_enabled = ?, jobtype_rate = ?,' . - ' jobtype_billable = ? WHERE jobtype_id = ?'; - $values = array($jobtype['name'], - (int)$jobtype['enabled'], - (float)$jobtype['rate'], - (int)$jobtype['billable'], - $jobtype['id']); - - try { - $this->_db->update($sql, $values); - } catch (Horde_Db_Exception $e) { - throw new Hermes_Exception($e); - } - - return $jobtype['id']; - } - } - - public function deleteJobType($jobTypeID) - { - try { - return $this->_db->delete('DELETE FROM hermes_jobtypes WHERE jobtype_id = ?', array($jobTypeID)); - } catch (Horde_Db_Exception $e) { - throw Hermes_Exception($e); - } - } - - /** - * @see Hermes_Driver::updateDeliverable - */ - public function updateDeliverable($deliverable) - { - if (empty($deliverable['id'])) { - $sql = 'INSERT INTO hermes_deliverables (' . - ' client_id, deliverable_name, deliverable_parent,' . - ' deliverable_estimate, deliverable_active,' . - ' deliverable_description) VALUES (?, ?, ?, ?, ?, ?)'; - $values = array($deliverable['client_id'], - $deliverable['name'], - (empty($deliverable['parent']) ? null : - (int)$deliverable['parent']), - (empty($deliverable['estimate']) ? null : - $deliverable['estimate']), - ($deliverable['active'] ? 1 : 0), - (empty($deliverable['description']) ? null : - $deliverable['description'])); - - try { - return $this->_db->insert($sql, $values); - } catch (Horde_Db_Exception $e) { - throw new Hermes_Exception($e); - } - } else { - $sql = 'UPDATE hermes_deliverables SET client_id = ?,' . - ' deliverable_name = ?, deliverable_parent = ?,' . - ' deliverable_estimate = ?, deliverable_active = ?,' . - ' deliverable_description = ? WHERE deliverable_id = ?'; - $values = array($deliverable['client_id'], - $deliverable['name'], - (empty($deliverable['parent']) ? null : - (int)$deliverable['parent']), - (empty($deliverable['estimate']) ? null : - $deliverable['estimate']), - ($deliverable['active'] ? 1 : 0), - (empty($deliverable['description']) ? null : - $deliverable['description']), - $deliverable['id']); - try { - $this->_db->update($sql, $values); - return $deliverable['id']; - } catch (Horde_Db_Exception $e) { - throw new Hermes_Exception($e); - } - } - } - - /** - * @see Hermes_Driver::listDeliverables() - */ - public function listDeliverables($criteria = array()) - { - $where = array(); - $values = array(); - if (isset($criteria['id'])) { - $where[] = 'deliverable_id = ?'; - $values[] = $criteria['id']; - } - if (isset($criteria['client_id'])) { - $where[] = 'client_id = ?'; - $values[] = $criteria['client_id']; - } - if (isset($criteria['active'])) { - if ($criteria['active']) { - $where[] = 'deliverable_active <> ?'; - } else { - $where[] = 'deliverable_active = ?'; - } - $values[] = 0; - } - - $sql = 'SELECT * FROM hermes_deliverables' . - (count($where) ? ' WHERE ' . join(' AND ', $where) : ''); - - try { - $rows = $this->_db->selectAll($sql, $values); - } catch (Horde_Db_Exception $e) { - throw new Hermes_Exception($e); - } - - $deliverables = array(); - foreach ($rows as $row) { - $deliverable = array('id' => $row['deliverable_id'], - 'client_id' => $row['client_id'], - 'name' => $row['deliverable_name'], - 'parent' => $row['deliverable_parent'], - 'estimate' => $row['deliverable_estimate'], - 'active' => !empty($row['deliverable_active']), - 'description' => $row['deliverable_description']); - $deliverables[$row['deliverable_id']] = $deliverable; - } - - return $deliverables; - } - - /** - * @see Hermes_Driver::updateDeliverable - * @throws Hermes_Exception - */ - public function deleteDeliverable($deliverableID) - { - $sql = 'SELECT COUNT(*) AS c FROM hermes_deliverables WHERE deliverable_parent = ?'; - $values = array($deliverableID); - - try { - $result = $this->_db->selectValue($sql, $values); - } catch (Horde_Db_Exception $e) { - throw new Hermes_Exception($e); - } - if (!empty($result)) { - throw new Hermes_Exception(_("Cannot delete deliverable; it has children.")); - } - - $sql = 'SELECT COUNT(*) AS c FROM hermes_timeslices WHERE costobject_id = ?'; - $values = array($deliverableID); - try { - $result = $this->_db->selectValue($sql, $values); - } catch (Horde_Db_Exception $e) { - throw new Hermes_Exception($e); - } - if (!empty($result)) { - throw Hermes_Exception(_("Cannot delete deliverable; there is time entered on it.")); - } - - $sql = 'DELETE FROM hermes_deliverables WHERE deliverable_id = ?'; - $values = array($deliverableID); - - try { - return $this->_db->delete($sql, $values); - } catch (Horde_Db_Exception $e) { - throw new Hermes_Exception($e); - } - } - - public function getClientSettings($clientID) - { - $clients = Hermes::listClients(); - if (empty($clientID) || !isset($clients[$clientID])) { - throw new Hermes_Exception('Does not exist'); - } - - $sql = 'SELECT clientjob_id, clientjob_enterdescription,' . - ' clientjob_exportid FROM hermes_clientjobs' . - ' WHERE clientjob_id = ?'; - $values = array($clientID); - - try { - $rows = $this->_db->selectAll($sql, $values); - } catch (Horde_Db_Exception $e) { - throw new Hermes_Exception($e); - } - $clientJob = array(); - foreach ($rows as $row) { - $clientJob[$row['clientjob_id']] = array($row['clientjob_enterdescription'], $row['clientjob_exportid']); - } - - if (isset($clientJob[$clientID])) { - $settings = array('id' => $clientID, - 'enterdescription' => $clientJob[$clientID][0], - 'exportid' => $clientJob[$clientID][1]); - } else { - $settings = array('id' => $clientID, - 'enterdescription' => 1, - 'exportid' => null); - } - - $settings['name'] = $clients[$clientID]; - return $settings; - } - - /** - * @TODO - * - * @param $clientID - * @param $enterdescription - * @param string $exportid - * @return - */ - public function updateClientSettings($clientID, $enterdescription = 1, $exportid = null) - { - if (empty($exportid)) { - $exportid = null; - } - - $sql = 'SELECT clientjob_id FROM hermes_clientjobs WHERE clientjob_id = ?'; - $values = array($clientID); - - if ($this->_db->selectValue($sql, $values) !== $clientID) { - $sql = 'INSERT INTO hermes_clientjobs (clientjob_id,' . - ' clientjob_enterdescription, clientjob_exportid)' . - ' VALUES (?, ?, ?)'; - $values = array($clientID, (int)$enterdescription, $exportid); - - try { - return $this->_db->insert($sql, $values); - } catch (Horde_Db_Exception $e) { - throw new Hermes_Exception($e); - } - } else { - $sql = 'UPDATE hermes_clientjobs SET' . - ' clientjob_exportid = ?, clientjob_enterdescription = ?' . - ' WHERE clientjob_id = ?'; - $values = array($exportid, (int)$enterdescription, $clientID); - - try { - return $this->_db->update($sql, $values); - } catch (Horde_Db_Exception $e) { - throw new Hermes_Exception($e); - } - } - } - - /** - * @TODO - * @global $conf - * @return - */ - public function purge() - { - global $conf; - - $query = 'DELETE FROM hermes_timeslices' . - ' WHERE timeslice_exported = ? AND timeslice_date < ?'; - $values = array(1, mktime(0, 0, 0, date('n'), - date('j') - $conf['time']['days_to_keep'])); - return $this->_db->delete($query, $values); - } - -}