<?php
/**
+ * The Horde_History:: system.
+ *
+ * PHP version 5
+ *
+ * @category Horde
+ * @package History
+ * @author Chuck Hagenbuch <chuck@horde.org>
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=History
+ */
+
+/**
+ * The Autoloader allows us to omit "require/include" statements.
+ */
+require_once 'Horde/Autoloader.php';
+
+/**
* The Horde_History:: class provides a method of tracking changes in Horde
* objects, stored in a SQL table.
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
- * @author Chuck Hagenbuch <chuck@horde.org>
- * @package Horde_History
+ * @category Horde
+ * @package History
+ * @author Chuck Hagenbuch <chuck@horde.org>
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=History
*/
class Horde_History
{
/**
- * Instance object.
- *
- * @var Horde_History
- */
- static protected $_instance;
-
- /**
- * Pointer to a DB instance to manage the history.
- *
- * @var DB
- */
- protected $_db;
-
- /**
- * Handle for the current database connection, used for writing. Defaults
- * to the same handle as $_db if a separate write database is not required.
+ * Instance cache.
*
- * @var DB
+ * @var array
*/
- protected $_write_db;
+ static protected $_instances;
/**
* Attempts to return a reference to a concrete History instance.
*
* This method must be invoked as: $var = History::singleton()
*
- * @return Horde_History The concrete Horde_History reference.
- * @throws Horde_Exception
- */
- static public function singleton()
- {
- if (!isset(self::$_instance)) {
- self::$_instance = new Horde_History();
- }
-
- return self::$_instance;
- }
-
- /**
- * Constructor.
+ * @param string $driver The driver to use.
*
+ * @return Horde_History The concrete Horde_History reference.
* @throws Horde_Exception
*/
- public function __construct()
+ static public function singleton($driver = null)
{
global $conf;
- if (empty($conf['sql']['phptype']) || ($conf['sql']['phptype'] == 'none')) {
- throw new Horde_Exception(_("The History system is disabled."));
+ if (empty($driver)) {
+ $driver = 'Sql';
}
- $this->_write_db = DB::connect($conf['sql']);
-
- /* Set DB portability options. */
- $portability = DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS;
-
- if (is_a($this->_write_db, 'DB_common')) {
- $write_portability = $portability;
- if ($this->_write_db->phptype == 'mssql') {
- $write_portability |= DB_PORTABILITY_RTRIM;
+ if ($driver == 'Sql') {
+ if (empty($conf['sql']['phptype'])
+ || ($conf['sql']['phptype'] == 'none')) {
+ throw new Horde_Exception(_("The History system is disabled."));
}
- $this->_write_db->setOption('portability', $write_portability);
+ $params = $conf['sql'];
+ } else {
+ $params = array();
}
- /* Check if we need to set up the read DB connection
- * seperately. */
- if (!empty($conf['sql']['splitread'])) {
- $params = array_merge($conf['sql'], $conf['sql']['read']);
- $this->_db = DB::connect($params);
-
- /* Set DB portability options. */
- if (is_a($this->_db, 'DB_common')) {
- $read_portability = $portability;
- if ($this->_db->phptype == 'mssql') {
- $read_portability |= DB_PORTABILITY_RTRIM;
- }
- $this->_db->setOption('portability', $read_portability);
- }
- } else {
- /* Default to the same DB handle for reads. */
- $this->_db =& $this->_write_db;
+ if (!isset(self::$_instances[$driver])) {
+ $injector = new Horde_Injector(new Horde_Injector_TopLevel());
+ $injector->bindFactory(
+ 'Horde_History',
+ 'Horde_History_Factory',
+ 'getHistory'
+ );
+ $config = new stdClass;
+ $config->driver = $driver;
+ $config->params = $params;
+ $injector->setInstance('Horde_History_Config', $config);
+ self::$_instances[$driver] = $injector->getInstance('Horde_History');
}
+
+ return self::$_instances[$driver];
}
/**
* 'ts' => Timestamp of the action (this will be added automatically if
* it is not present).
*
- * @param string $guid The unique identifier of the entry to
- * add to.
- * @param array $attributes The hash of name => value entries that
- * describe this event.
- * @param boolean $replaceAction If $attributes['action'] is already
- * present in the item's history log,
- * update that entry instead of creating a
- * new one.
+ * @param string $guid The unique identifier of the entry to
+ * add to.
+ * @param array $attributes The hash of name => value entries that
+ * describe this event.
+ * @param boolean $replaceAction If $attributes['action'] is already
+ * present in the item's history log,
+ * update that entry instead of creating a
+ * new one.
+ *
+ * @return boolean True if the operation succeeded.
*
* @throws Horde_Exception
*/
- public function log($guid, $attributes = array(), $replaceAction = false)
+ public function log($guid, array $attributes = array(),
+ $replaceAction = false)
{
$history = $this->getHistory($guid);
$attributes['ts'] = time();
}
- /* If we want to replace an entry with the same action, try and find
- * one. Track whether or not we succeed in $done, so we know whether
- * or not to add the entry later. */
- $done = false;
- if ($replaceAction && !empty($attributes['action'])) {
- for ($i = 0, $count = count($history->data); $i < $count; ++$i) {
- if (!empty($history->data[$i]['action']) &&
- $history->data[$i]['action'] == $attributes['action']) {
- $values = array(
- $attributes['ts'],
- $attributes['who'],
- isset($attributes['desc']) ? $attributes['desc'] : null
- );
-
- unset($attributes['ts'], $attributes['who'], $attributes['desc'], $attributes['action']);
-
- $values[] = $attributes
- ? serialize($attributes)
- : null;
- $values[] = $history->data[$i]['id'];
-
- $r = $this->_write_db->query(
- 'UPDATE horde_histories SET history_ts = ?,' .
- ' history_who = ?,' .
- ' history_desc = ?,' .
- ' history_extra = ? WHERE history_id = ?', $values
- );
-
- if ($r instanceof PEAR_Error) {
- Horde::logMessage($r, __FILE__, __LINE__, PEAR_LOG_ERR);
- throw new Horde_Exception($r->getMessage());
- }
- $done = true;
- break;
- }
- }
- }
-
- /* If we're not replacing by action, or if we didn't find an entry to
- * replace, insert a new row. */
- if (!$done) {
- $history_id = $this->_write_db->nextId('horde_histories');
- if ($history_id instanceof PEAR_Error) {
- Horde::logMessage($history_id, __FILE__, __LINE__, PEAR_LOG_ERR);
- throw new Horde_Exception($history_id->getMessage());
- }
-
- $values = array(
- $history_id,
- $guid,
- $attributes['ts'],
- $attributes['who'],
- isset($attributes['desc']) ? $attributes['desc'] : null,
- isset($attributes['action']) ? $attributes['action'] : null
- );
-
- unset($attributes['ts'], $attributes['who'], $attributes['desc'], $attributes['action']);
-
- $values[] = $attributes
- ? serialize($attributes)
- : null;
-
- $r = $this->_write_db->query(
- 'INSERT INTO horde_histories (history_id, object_uid, history_ts, history_who, history_desc, history_action, history_extra)' .
- ' VALUES (?, ?, ?, ?, ?, ?, ?)', $values
- );
-
- if ($r instanceof PEAR_Error) {
- Horde::logMessage($r, __FILE__, __LINE__, PEAR_LOG_ERR);
- throw new Horde_Exception($r->getMessage());
- }
- }
+ return $this->_log($history, $attributes, $replaceAction);
+ }
- return true;
+ /**
+ * Logs an event to an item's history log. Any other details about the event
+ * are passed in $attributes.
+ *
+ * @param Horde_HistoryObject $history The history item to add to.
+ * @param array $attributes The hash of name => value entries
+ * that describe this event.
+ * @param boolean $replaceAction If $attributes['action'] is
+ * already present in the item's
+ * history log, update that entry
+ * instead of creating a new one.
+ *
+ * @return boolean True if the operation succeeded.
+ *
+ * @throws Horde_Exception
+ */
+ protected function _log(Horde_HistoryObject $history, array $attributes,
+ $replaceAction = false)
+ {
+ throw new Horde_Exception('Not implemented!');
}
/**
* Returns a Horde_HistoryObject corresponding to the named history
* entry, with the data retrieved appropriately.
*
- * @param string $guid The name of the history entry to retrieve.
+ * @param string $guid The name of the history entry to retrieve.
+ *
+ * @return Horde_HistoryObject A Horde_HistoryObject
*
- * @return Horde_HistoryObject A Horde_HistoryObject
+ * @throws Horde_Exception
*/
public function getHistory($guid)
{
- $rows = $this->_db->getAll('SELECT * FROM horde_histories WHERE object_uid = ?', array($guid), DB_FETCHMODE_ASSOC);
- return new Horde_HistoryObject($guid, $rows);
+ throw new Horde_Exception('Not implemented!');
}
/**
* Finds history objects by timestamp, and optionally filter on other
* fields as well.
*
- * @param string $cmp The comparison operator (<, >, <=, >=, or =) to
- * check the timestamps with.
- * @param integer $ts The timestamp to compare against.
- * @param array $filters An array of additional (ANDed) criteria.
- * Each array value should be an array with 3
- * entries:
+ * @param string $cmp The comparison operator (<, >, <=, >=, or =) to
+ * check the timestamps with.
+ * @param integer $ts The timestamp to compare against.
+ * @param array $filters An array of additional (ANDed) criteria.
+ * Each array value should be an array with 3
+ * entries:
* <pre>
* 'field' - the history field being compared (i.e. 'action').
* 'op' - the operator to compare this field with.
* 'value' - the value to check for (i.e. 'add').
* </pre>
- * @param string $parent The parent history to start searching at. If
- * non-empty, will be searched for with a LIKE
- * '$parent:%' clause.
+ * @param string $parent The parent history to start searching at. If
+ * non-empty, will be searched for with a LIKE
+ * '$parent:%' clause.
*
* @return array An array of history object ids, or an empty array if
* none matched the criteria.
+ *
+ * @throws Horde_Exception
*/
- public function getByTimestamp($cmp, $ts, $filters = array(),
+ public function getByTimestamp($cmp, $ts, array $filters = array(),
$parent = null)
{
- /* Build the timestamp test. */
- $where = array("history_ts $cmp $ts");
-
- /* Add additional filters, if there are any. */
- if ($filters) {
- foreach ($filters as $filter) {
- $where[] = 'history_' . $filter['field'] . ' ' . $filter['op'] . ' ' . $this->_db->quote($filter['value']);
- }
- }
-
- if ($parent) {
- $where[] = 'object_uid LIKE ' . $this->_db->quote($parent . ':%');
- }
-
- return $this->_db->getAssoc('SELECT DISTINCT object_uid, history_id FROM horde_histories WHERE ' . implode(' AND ', $where));
+ throw new Horde_Exception('Not implemented!');
}
/**
* Gets the timestamp of the most recent change to $guid.
*
- * @param string $guid The name of the history entry to retrieve.
- * @param string $action An action: 'add', 'modify', 'delete', etc.
+ * @param string $guid The name of the history entry to retrieve.
+ * @param string $action An action: 'add', 'modify', 'delete', etc.
*
* @return integer The timestamp, or 0 if no matching entry is found.
+ *
* @throws Horde_Exception
*/
public function getActionTimestamp($guid, $action)
/**
* Remove one or more history entries by name.
*
- * @param array $names The history entries to remove.
+ * @param array $names The history entries to remove.
+ *
+ * @return boolean True if the operation succeeded.
+ *
+ * @throws Horde_Exception
*/
- public function removeByNames($names)
+ public function removeByNames(array $names)
{
- if (!count($names)) {
- return true;
- }
-
- $ids = array();
- foreach ($names as $name) {
- $ids[] = $this->_write_db->quote($name);
- }
-
- return $this->_write_db->query('DELETE FROM horde_histories WHERE object_uid IN (' . implode(',', $ids) . ')');
+ throw new Horde_Exception('Not implemented!');
}
}
--- /dev/null
+<?php
+/**
+ * A factory for history handlers.
+ *
+ * PHP version 5
+ *
+ * @category Horde
+ * @package History
+ * @author Chuck Hagenbuch <chuck@horde.org>
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=History
+ */
+
+/**
+ * The Autoloader allows us to omit "require/include" statements.
+ */
+require_once 'Horde/Autoloader.php';
+
+/**
+ * The Horde_History_Factory:: provides a method for generating
+ * a Horde_History handler.
+ *
+ * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @category Horde
+ * @package History
+ * @author Chuck Hagenbuch <chuck@horde.org>
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=History
+ */
+class Horde_History_Factory
+{
+ /**
+ * Create a concrete Horde_History instance.
+ *
+ * @param Horde_Injector $injector The environment for creating the instance.
+ *
+ * @return Horde_History The new Horde_History instance.
+ *
+ * @throws Horde_Exception If the injector provides no configuration.
+ */
+ static public function getHistory(Horde_Injector $injector)
+ {
+ try {
+ $config = $injector->getInstance('Horde_History_Config');
+ } catch (ReflectionException $e) {
+ throw new Horde_Exception(
+ sprintf(
+ 'The configuration for the History driver is missing: %s',
+ $e->getMessage()
+ )
+ );
+ }
+
+ switch (ucfirst($config->driver)) {
+ case 'Sql':
+ return Horde_History_Factory::getHistorySql($injector, $config->params);
+ case 'Mock':
+ default:
+ return Horde_History_Factory::getHistoryMock($config->params);
+ }
+ }
+
+ /**
+ * Create a concrete Horde_History_Sql instance.
+ *
+ * @param Horde_Injector $injector The environment for creating the instance.
+ * @param array $params The db connection parameters if the
+ * environment does not already provide a
+ * connection.
+ *
+ * @return Horde_History_Sql The new Horde_History_Sql instance.
+ *
+ * @throws Horde_Exception If the injector provides no configuration or
+ * creating the database connection failed.
+ */
+ static protected function getHistorySql(Horde_Injector $injector, array $params)
+ {
+ try {
+ /** See if there is a specific write db instance available */
+ $write_db = $injector->getInstance('DB_common_write');
+ $history = new Horde_History_Sql($write_db);
+ try {
+ /** See if there is a specific read db instance available */
+ $read_db = $injector->getInstance('DB_common_read');
+ $history->setReadDb($read_db);
+ } catch (ReflectionException $e) {
+ }
+ } catch (ReflectionException $e) {
+ /** No DB instances. Use the configuration. */
+ $write_db = Horde_History_Factory::getDb($params);
+
+ $history = new Horde_History_Sql($write_db);
+
+ /* Check if we need to set up the read DB connection
+ * seperately. */
+ if (!empty($params['splitread'])) {
+ $params = array_merge($params, $params['read']);
+ $read_db = Horde_History_Factory::getDb($params);
+ $history->setReadDb($read_db);
+ }
+ }
+ return $history;
+ }
+
+ /**
+ * Create a database connection.
+ *
+ * @param array $params The database connection parameters.
+ *
+ * @return DB_common
+ *
+ * @throws Horde_Exception In case the database connection failed.
+ */
+ static protected function getDb(array $params)
+ {
+ $db = DB::connect($params);
+
+ /* Set DB portability options. */
+ $portability = DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS;
+
+ if ($db instanceOf DB_common) {
+ if ($db->phptype == 'mssql') {
+ $portability |= DB_PORTABILITY_RTRIM;
+ }
+ $db->setOption('portability', $portability);
+ } else if ($db instanceOf PEAR_Error) {
+ throw new Horde_Exception($db->getMessage());
+ }
+ return $db;
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * A sql based history driver.
+ *
+ * PHP version 5
+ *
+ * @category Horde
+ * @package History
+ * @author Chuck Hagenbuch <chuck@horde.org>
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=History
+ */
+
+/**
+ * The Horde_History_Sql:: class provides a method of tracking changes in Horde
+ * objects, stored in a SQL table.
+ *
+ * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @category Horde
+ * @package History
+ * @author Chuck Hagenbuch <chuck@horde.org>
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=History
+ */
+class Horde_History_Sql extends Horde_History
+{
+ /**
+ * Pointer to a DB instance to manage the history.
+ *
+ * @var DB
+ */
+ protected $_db;
+
+ /**
+ * Handle for the current database connection, used for writing. Defaults
+ * to the same handle as $_db if a separate write database is not required.
+ *
+ * @var DB
+ */
+ protected $_write_db;
+
+ /**
+ * Constructor.
+ *
+ * @param DB_common $db The database connection.
+ */
+ public function __construct(DB_common $db)
+ {
+ $this->_write_db = $db;
+ $this->_db = $db;
+ }
+
+ /**
+ * Set a separate read database connection if you want to split read and
+ * write access to the db.
+ *
+ * @param DB_common $db The database connection.
+ *
+ * @return NULL
+ */
+ public function setReadDb(DB_common $db)
+ {
+ $this->_db = $db;
+ }
+
+ /**
+ * Logs an event to an item's history log. Any other details about the event
+ * are passed in $attributes.
+ *
+ * @param Horde_HistoryObject $history The history item to add to.
+ * @param array $attributes The hash of name => value entries
+ * that describe this event.
+ * @param boolean $replaceAction If $attributes['action'] is
+ * already present in the item's
+ * history log, update that entry
+ * instead of creating a new one.
+ *
+ * @return boolean True if the operation succeeded.
+ *
+ * @throws Horde_Exception
+ */
+ protected function _log(Horde_HistoryObject $history,
+ array $attributes,
+ $replaceAction = false)
+ {
+ /* If we want to replace an entry with the same action, try and find
+ * one. Track whether or not we succeed in $done, so we know whether
+ * or not to add the entry later. */
+ $done = false;
+ if ($replaceAction && !empty($attributes['action'])) {
+ for ($i = 0, $count = count($history->data); $i < $count; ++$i) {
+ if (!empty($history->data[$i]['action']) &&
+ $history->data[$i]['action'] == $attributes['action']) {
+ $values = array(
+ $attributes['ts'],
+ $attributes['who'],
+ isset($attributes['desc']) ? $attributes['desc'] : null
+ );
+
+ unset($attributes['ts'], $attributes['who'],
+ $attributes['desc'], $attributes['action']);
+
+ $values[] = $attributes
+ ? serialize($attributes)
+ : null;
+ $values[] = $history->data[$i]['id'];
+
+ $r = $this->_write_db->query(
+ 'UPDATE horde_histories SET history_ts = ?,' .
+ ' history_who = ?,' .
+ ' history_desc = ?,' .
+ ' history_extra = ? WHERE history_id = ?', $values
+ );
+
+ if ($r instanceof PEAR_Error) {
+ Horde::logMessage($r, __FILE__, __LINE__, PEAR_LOG_ERR);
+ throw new Horde_Exception($r->getMessage());
+ }
+ $done = true;
+ break;
+ }
+ }
+ }
+
+ /* If we're not replacing by action, or if we didn't find an entry to
+ * replace, insert a new row. */
+ if (!$done) {
+ $history_id = $this->_write_db->nextId('horde_histories');
+ if ($history_id instanceof PEAR_Error) {
+ Horde::logMessage($history_id, __FILE__, __LINE__, PEAR_LOG_ERR);
+ throw new Horde_Exception($history_id->getMessage());
+ }
+
+ $values = array(
+ $history_id,
+ $history->uid,
+ $attributes['ts'],
+ $attributes['who'],
+ isset($attributes['desc']) ? $attributes['desc'] : null,
+ isset($attributes['action']) ? $attributes['action'] : null
+ );
+
+ unset($attributes['ts'], $attributes['who'],
+ $attributes['desc'], $attributes['action']);
+
+ $values[] = $attributes
+ ? serialize($attributes)
+ : null;
+
+ $r = $this->_write_db->query(
+ 'INSERT INTO horde_histories (history_id, object_uid, history_ts, history_who, history_desc, history_action, history_extra)' .
+ ' VALUES (?, ?, ?, ?, ?, ?, ?)', $values
+ );
+
+ if ($r instanceof PEAR_Error) {
+ Horde::logMessage($r, __FILE__, __LINE__, PEAR_LOG_ERR);
+ throw new Horde_Exception($r->getMessage());
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns a Horde_HistoryObject corresponding to the named history
+ * entry, with the data retrieved appropriately.
+ *
+ * @param string $guid The name of the history entry to retrieve.
+ *
+ * @return Horde_HistoryObject A Horde_HistoryObject
+ */
+ public function getHistory($guid)
+ {
+ $rows = $this->_db->getAll('SELECT * FROM horde_histories WHERE object_uid = ?', array($guid), DB_FETCHMODE_ASSOC);
+ return new Horde_HistoryObject($guid, $rows);
+ }
+
+ /**
+ * Finds history objects by timestamp, and optionally filter on other
+ * fields as well.
+ *
+ * @param string $cmp The comparison operator (<, >, <=, >=, or =) to
+ * check the timestamps with.
+ * @param integer $ts The timestamp to compare against.
+ * @param array $filters An array of additional (ANDed) criteria.
+ * Each array value should be an array with 3
+ * entries:
+ * <pre>
+ * 'field' - the history field being compared (i.e. 'action').
+ * 'op' - the operator to compare this field with.
+ * 'value' - the value to check for (i.e. 'add').
+ * </pre>
+ * @param string $parent The parent history to start searching at. If
+ * non-empty, will be searched for with a LIKE
+ * '$parent:%' clause.
+ *
+ * @return array An array of history object ids, or an empty array if
+ * none matched the criteria.
+ *
+ * @throws Horde_Exception
+ */
+ public function getByTimestamp($cmp, $ts, $filters = array(),
+ $parent = null)
+ {
+ /* Build the timestamp test. */
+ $where = array("history_ts $cmp $ts");
+
+ /* Add additional filters, if there are any. */
+ if ($filters) {
+ foreach ($filters as $filter) {
+ $where[] = 'history_' . $filter['field'] . ' ' . $filter['op'] . ' ' . $this->_db->quote($filter['value']);
+ }
+ }
+
+ if ($parent) {
+ $where[] = 'object_uid LIKE ' . $this->_db->quote($parent . ':%');
+ }
+
+ return $this->_db->getAssoc('SELECT DISTINCT object_uid, history_id FROM horde_histories WHERE ' . implode(' AND ', $where));
+ }
+
+ /**
+ * Gets the timestamp of the most recent change to $guid.
+ *
+ * @param string $guid The name of the history entry to retrieve.
+ * @param string $action An action: 'add', 'modify', 'delete', etc.
+ *
+ * @return integer The timestamp, or 0 if no matching entry is found.
+ *
+ * @throws Horde_Exception
+ */
+ public function getActionTimestamp($guid, $action)
+ {
+ /* This implementation still works, but we should be able to
+ * get much faster now with a SELECT MAX(history_ts)
+ * ... query. */
+ try {
+ $history = $this->getHistory($guid);
+ } catch (Horde_Exception $e) {
+ return 0;
+ }
+
+ $last = 0;
+
+ if (is_array($history->data)) {
+ foreach ($history->data as $entry) {
+ if (($entry['action'] == $action) && ($entry['ts'] > $last)) {
+ $last = $entry['ts'];
+ }
+ }
+ }
+
+ return (int)$last;
+ }
+
+ /**
+ * Remove one or more history entries by name.
+ *
+ * @param array $names The history entries to remove.
+ *
+ * @return boolean True if the operation succeeded.
+ *
+ * @throws Horde_Exception
+ */
+ public function removeByNames($names)
+ {
+ if (!count($names)) {
+ return true;
+ }
+
+ $ids = array();
+ foreach ($names as $name) {
+ $ids[] = $this->_write_db->quote($name);
+ }
+
+ return $this->_write_db->query('DELETE FROM horde_histories WHERE object_uid IN (' . implode(',', $ids) . ')');
+ }
+
+}
<dir name="Horde">
<file name="History.php" role="php" />
<file name="HistoryObject.php" role="php" />
+ <dir name="History">
+ <file name="Factory.php" role="php" />
+ <file name="Sql.php" role="php" />
+ </dir> <!-- /lib/Horde/History -->
</dir> <!-- /lib/Horde -->
</dir> <!-- /lib -->
<dir name="test">
<filelist>
<install name="lib/Horde/History.php" as="Horde/History.php" />
<install name="lib/Horde/HistoryObject.php" as="Horde/HistoryObject.php" />
+ <install name="lib/Horde/History/Factory.php" as="Horde/History/Factory.php" />
+ <install name="lib/Horde/History/Sql.php" as="Horde/History/Sql.php" />
<install name="test/Horde/History/AllTests.php" as="Horde/History/AllTests.php" />
<install name="test/Horde/History/InterfaceTest.php" as="Horde/History/InterfaceTest.php" />
</filelist>
*/
private $_db_file;
-
- public function setUp()
- {
- }
-
+ /**
+ * Test cleanup.
+ */
public function tearDown()
{
if (!empty($this->_db_file)) {
public function getEnvironments()
{
if (empty($this->_environments)) {
- /** The db environment provides our only test scenario before refactoring */
+ /**
+ * The db environment provides our only test scenario before
+ * refactoring.
+ */
$this->_environments = array(self::ENVIRONMENT_DB);
}
return $this->_environments;
$conf['sql']['charset'] = 'utf-8';
$conf['sql']['phptype'] = 'sqlite';
- $history = new Horde_History();
+ $injector = new Horde_Injector(new Horde_Injector_TopLevel());
+ $injector->bindFactory(
+ 'Horde_History',
+ 'Horde_History_Factory',
+ 'getHistory'
+ );
+
+ $config = new stdClass;
+ $config->driver = 'Sql';
+ $config->params = $conf['sql'];
+ $injector->setInstance('Horde_History_Config', $config);
+
+ $history = $injector->getInstance('Horde_History');
break;
}
}
foreach ($this->getEnvironments() as $environment) {
$history = $this->getHistory($environment);
$history1 = Horde_History::singleton();
+ $this->assertType('Horde_History', $history1);
$history2 = Horde_History::singleton();
+ $this->assertType('Horde_History', $history2);
$this->assertSame($history1, $history2);
}
}
$history = $this->getHistory($environment);
$history->log('test', array('action' => 'test'));
$this->assertTrue($history->getActionTimestamp('test', 'test') > 0);
- $data = $history->getHistory('test')->getData();
+ $data = $history->getHistory('test')->getData();
$this->assertTrue(isset($data[0]['who']));
}
}
'who' => 'you',
'id' => 2,
'ts' => 2000,
- 'extra' => array('a' => 'a'),
+ 'extra' => array('a' => 'a'),
),
);
$this->assertEquals($expect, $data);
$history = $this->getHistory($environment);
$history->log('test', array('who' => 'me', 'ts' => 1000, 'action' => 'test'));
$history->log('test', array('who' => 'you', 'ts' => 2000, 'action' => 'yours', 'extra' => array('a' => 'a')));
- $result = $history->getByTimestamp('>', 1, array(array('field' => 'who', 'op' => '=', 'value' => 'you')));
+ $result = $history->getByTimestamp('>', 1, array(array('field' => 'who', 'op' => '=', 'value' => 'you')));
$this->assertEquals(array('test' => 2), $result);
}
}
$history->log('test:a', array('who' => 'me', 'ts' => 1000, 'action' => 'test'));
$history->log('test:b', array('who' => 'you', 'ts' => 2000, 'action' => 'yours'));
$history->log('yours', array('who' => 'you', 'ts' => 3000, 'action' => 'yours'));
- $result = $history->getByTimestamp('>', 1, array(), 'test');
+ $result = $history->getByTimestamp('>', 1, array(), 'test');
$this->assertEquals(array('test:a' => 1, 'test:b' => 2), $result);
}
}
$history = $this->getHistory($environment);
$history->log('test', array('who' => 'me', 'ts' => 1000, 'action' => 'test'));
$history->log('test', array('who' => 'you', 'ts' => 2000, 'action' => 'yours', 'extra' => array('a' => 'a')));
- $result = $history->getByTimestamp('<', 1001);
+ $result = $history->getByTimestamp('<', 1001);
$this->assertEquals(array('test' => 1), $result);
}
}