steffen: server/kolab-horde-framework/kolab-horde-framework/History History.php, NONE, 1.1 package.xml, NONE, 1.1
cvs at intevation.de
cvs at intevation.de
Fri Oct 14 16:33:06 CEST 2005
Author: steffen
Update of /kolabrepository/server/kolab-horde-framework/kolab-horde-framework/History
In directory doto:/tmp/cvs-serv28903/kolab-horde-framework/kolab-horde-framework/History
Added Files:
History.php package.xml
Log Message:
Separated Horde Framework from kolab-resource-handlers
--- NEW FILE: History.php ---
<?php
require_once 'Horde/DataTree.php';
/**
* The History:: class provides a method of tracking changes in Horde
* objects using the Horde DataTree backend.
*
* $Horde: framework/History/History.php,v 1.17 2004/04/07 14:43:08 chuck Exp $
*
* Copyright 2003-2004 Chuck Hagenbuch <chuck at 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.
*
* @author Chuck Hagenbuch <chuck at horde.org>
* @version $Revision: 1.1 $
* @since Horde 2.1
* @package Horde_History
*/
class Horde_History {
/**
* Pointer to a DataTree instance to manage the history.
* @var object DataTree $_datatree
*/
var $_datatree;
/**
* Constructor.
*/
function Horde_History()
{
global $conf;
if (!isset($conf['datatree']['driver'])) {
Horde::fatal('You must configure a DataTree backend to use History.');
}
$driver = $conf['datatree']['driver'];
$this->_datatree = &DataTree::singleton($driver,
array_merge(Horde::getDriverConfig('datatree', $driver),
array('group' => 'horde.history')));
}
/**
* Log an event to an item's history log. The item must be
* uniquely identified by $itemGuid. Any other details about the
* event are passed in $attributes. Standard suggested attributes
* are:
*
* 'who' => The id of the user that performed the action (will
* be added automatically if not present).
*
* 'ts' => Timestamp of the action (this will be added
* automatically if it is not present).
*
* 'desc' => Text description of the action (this may contain a
* %s to represent the date of the action).
*
* @access public.
*
* @param string $guid The unique identifier of the entry to add to.
* @param array $attributes (optional) The hash of name => value entries that describe this event.
* @param boolean $replaceAction (optional) If $attributes['action'] is already present in the
* item's history log, update that entry instead of creating
* a new one.
*
* @return boolean|object PEAR_Error True on success, or a PEAR_Error object on failure.
*/
function log($guid, $attributes = array(), $replaceAction = false)
{
$history = &$this->getHistory($guid, true);
if (is_a($history, 'PEAR_Error')) {
return $history;
}
$history->log($attributes, $replaceAction);
return $this->_updateHistory($history);
}
/**
* Return a DataTreeObject_History object corresponding to the
* named history entry, with the data retrieved appropriately. If
* $autocreate is true, and $guid does not already exist, create,
* save, and return a new History object with this $id.
*
* @param optional boolean $autocreate Automatically create the history entry?
*
* @param string $guid The name of the history entry to retrieve.
*/
function &getHistory($guid, $autocreate = false)
{
// If the $guid doesn't already contain a specified parent id,
// then use the current application name as the parent
// object.
if (!strstr($guid, ':')) {
global $registry;
$guid = $registry->getApp() . ':' . $guid;
}
if ($this->_datatree->exists($guid)) {
$history = &$this->_getHistory($guid);
} elseif ($autocreate) {
$history = &$this->_newHistory($guid);
$result = $this->_addHistory($history);
if (is_a($result, 'PEAR_Error')) {
return $result;
}
} else {
// Return an empty history object for ease of use.
$history = &new DataTreeObject_History($guid);
$history->setHistoryOb($this);
}
return $history;
}
/**
* Find 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 (optional) An array of additional (ANDed) criteria.
* each array value should be an array with 3 entries:
* 'op' - the operator to compare this field with.
* 'field' - the history field being compared (i.e., 'action').
* 'value' - the value to check for (i.e., 'add').
* @param string $parent (optional) The parent history to start searching at.
*
* @return array An array of history object ids, or an empty array
* if none matched the criteria.
*/
function &getByTimestamp($cmp, $ts, $filters = array(), $parent = '-1')
{
// Build the timestamp test.
$criteria = array(
array('field' => 'key', 'op' => '=', 'test' => 'ts'),
array('field' => 'value', 'op' => $cmp, 'test' => $ts));
// Add additional filters, if there are any.
if (count($filters)) {
foreach ($filters as $filter) {
$criteria[] = array('JOIN' => array(
array('field' => 'key', 'op' => '=', 'test' => $filter['field']),
array('field' => 'value', 'op' => $filter['op'], 'test' => $filter['value'])));
}
}
// Everything is ANDed together.
$criteria = array('AND' => $criteria);
$histories = $this->_datatree->getByAttributes($criteria, $parent);
if (is_a($histories, 'PEAR_Error') || !count($histories)) {
// If we got back an error or an empty array, just return
// it.
return $histories;
}
return $this->_getHistories(array_keys($histories));
}
/**
* Return a DataTreeObject_History object corresponding to the
* named history entry, with the data retrieved appropriately.
*
* @param string $guid The name of the history entry to retrieve.
*/
function &_getHistory($guid)
{
/* Cache of previous retrieved history entries. */
static $historyCache;
if (!is_array($historyCache)) {
$historyCache = array();
}
if (!isset($historyCache[$guid])) {
$historyCache[$guid] = $this->_datatree->getObject($guid, 'DataTreeObject_History');
if (!is_a($historyCache[$guid], 'PEAR_Error')) {
$historyCache[$guid]->setHistoryOb($this);
}
}
return $historyCache[$guid];
}
/**
* Return an array of DataTreeObject_History objects corresponding
* to the given set of unique IDs, with the details retrieved
* appropriately.
*
* @param array $guids The array of ids to retrieve.
*/
function &_getHistories($guids)
{
$histories = &$this->_datatree->getObjects($guids, 'DataTreeObject_History');
if (is_a($histories, 'PEAR_Error')) {
return $histories;
}
$keys = array_keys($histories);
foreach ($keys as $key) {
if (!is_a($histories[$key], 'PEAR_Error')) {
$histories[$key]->setHistoryOb($this);
}
}
return $histories;
}
/**
* Change the name of a history entry without changing its
* contents.
*
* @param object DataTreeObject_History $history The history entry to rename.
* @param string $newName The entry's new name.
*/
function rename($history, $newName)
{
if (!is_a($history, 'DataTreeObject_History')) {
return PEAR::raiseError('History entries must be DataTreeObject_History objects or extend that class.');
}
return $this->_datatree->rename($history, $newName);
}
/**
* Copy a history entry's data to a new name, keeping the old
* entry as well.
*
* @param object DataTreeObject_History $history The history entry to rename.
* @param string $newName The entry's new name.
*/
function copy($history, $newName)
{
if (!is_a($history, 'DataTreeObject_History')) {
return PEAR::raiseError('History entries must be DataTreeObject_History objects or extend that class.');
}
$new = &$this->_newHistory($newName);
$new->data = $history->data;
return $this->_addHistory($new);
}
/**
* Remove a history entry from the history system permanently.
*
* @param object DataTreeObject_History $history The history entry to remove.
*/
function removeHistory($history)
{
if (!is_a($history, 'DataTreeObject_History')) {
return PEAR::raiseError('History entries must be DataTreeObject_History objects or extend that class.');
}
return $this->_datatree->remove($history, false);
}
/**
* Get a list of every history entry, in the format cid =>
* historyname.
*
* @return array CID => historyname hash.
*/
function listHistories()
{
static $entries;
if (is_null($entries)) {
$entries = $this->_datatree->get(DATATREE_FORMAT_FLAT, '-1', true);
unset($entries['-1']);
}
return $entries;
}
/**
* Return a new history entry object.
*
* @access private
*
* @param string $guid The entry's name.
*
* @return object DataTreeObject_History A new history entry object.
*/
function &_newHistory($guid)
{
if (empty($guid)) {
return PEAR::raiseError(_("History entry names must be non-empty"));
}
$history = &new DataTreeObject_History($guid);
$history->setHistoryOb($this);
return $history;
}
/**
* Add an entry to the history system. The entry must first be
* created with &History::_newHistory() before this function is
* called.
*
* @access private
*
* @param object DataTreeObject_History $history The new history entry object.
*/
function _addHistory($history)
{
if (!is_a($history, 'DataTreeObject_History')) {
return PEAR::raiseError('History entries must be DataTreeObject_History objects or extend that class.');
}
return $this->_datatree->add($history);
}
/**
* Store updated data of a history to the backend system.
*
* @access private
*
* @param object DataTreeObject_History $history The history entry to update.
*/
function _updateHistory($history)
{
if (!is_a($history, 'DataTreeObject_History')) {
return PEAR::raiseError('History entries must be DataTreeObject_History objects or extend that class.');
}
return $this->_datatree->updateData($history);
}
/**
* Attempts to return a reference to a concrete History instance.
* It will only create a new instance if no History instance
* currently exists.
*
* This method must be invoked as: $var = &History::singleton()
*
* @return object Horde_History The concrete History reference, or false on an
* error.
*/
function &singleton()
{
static $history;
if (!isset($history)) {
$history = new Horde_History();
}
return $history;
}
}
/**
* Extension of the DataTreeObject class for storing History information
* in the DataTree backend. If you want to store specialized History
* information, you should extend this class instead of extending
* DataTreeObject directly.
*
* @author Chuck Hagenbuch <chuck at horde.org>
* @version $Revision: 1.1 $
* @since Horde 2.1
* @package Horde_History
*/
class DataTreeObject_History extends DataTreeObject {
/**
* The History object which this history came from - needed for
* updating data in the backend to make changes stick, etc.
*
* @var object History $historyOb
*/
var $_historyOb;
/**
* Associates a History object with this history.
*
* @param object History $historyOb The History object.
*/
function setHistoryOb(&$historyOb)
{
$this->_historyOb = &$historyOb;
}
/**
* Log an event to this item's history log. Details about the
* event are passed in $attributes. Standard suggested attributes
* are:
*
* 'who' => The id of the user that performed the action (will
* be added automatically if not present).
*
* 'ts' => Timestamp of the action (this will be added
* automatically if it is not present).
*
* 'desc' => Text description of the action (this may contain a
* %s to represent the date of the action).
*
* @access public.
*
* @param array $attributes The hash of name => value entries that describe this event.
* @param boolean $replaceAction (optional) If $attributes['action'] is already present in the
* item's history log, update that entry instead of creating
* a new one.
*
* @return boolean|object PEAR_Error True on success, or a PEAR_Error object on failure.
*/
function log($attributes = array(), $replaceAction = false)
{
if (empty($attributes['who'])) {
$attributes['who'] = Auth::getAuth();
}
if (empty($attributes['ts'])) {
$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'])) {
$count = count($this->data);
for ($i = 0; $i < $count; $i++) {
if (!empty($this->data[$i]['action']) &&
$this->data[$i]['action'] == $attributes['action']) {
$this->data[$i] = $attributes;
$done = true;
break;
}
}
}
// If we're not replacing by action, or if we didn't find an
// entry to replace, tack $attributes onto the end of the
// $data array.
if (!$done) {
$this->data[] = $attributes;
}
}
/**
* Format the description from a history entry using the default
* timestamp format or a specified one.
*
* @param array $entry The history entry.
* @param optional string $format The format string to use for the timestamp.
*
* @return string The formatted description.
*/
function getDescription($entry, $format = '%x %X')
{
return @sprintf($entry['desc'], strftime($format, $entry['ts']));
}
/**
* Save any changes to this object to the backend permanently.
*/
function save()
{
$this->_historyOb->_updateHistory($this);
}
/**
* Map this object's attributes from the data array into a format
* that we can store in the attributes storage backend.
*
* @return array The attributes array.
*/
function _toAttributes()
{
// Default to no attributes.
$attributes = array();
// Loop through all users, if any.
foreach ($this->data as $index => $entry) {
foreach ($entry as $key => $value) {
$attributes[] = array('name' => (string)$index,
'key' => (string)$key,
'value' => (string)$value);
}
}
return $attributes;
}
/**
* Take in a list of attributes from the backend and map it to our
* internal data array.
*
* @param array $attributes The list of attributes from the
* backend (attribute name, key, and value).
*/
function _fromAttributes($attributes)
{
// Initialize data array.
$this->data = array();
foreach ($attributes as $attr) {
if (!isset($this->data[$attr['name']])) {
$this->data[$attr['name']] = array();
}
$this->data[$attr['name']][$attr['key']] = $attr['value'];
}
}
}
--- NEW FILE: package.xml ---
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!-- $Horde: framework/History/package.xml,v 1.1 2004/01/25 19:21:29 chuck Exp $ -->
<!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.1">
<package version="1.0">
<name>Horde_History</name>
<summary>API for tracking the history of an object.</summary>
<description>
This API provides a way to track changes on arbitrary pieces of
data in Horde applications.
</description>
<license>LGPL</license>
<maintainers>
<maintainer>
<user>chuck</user>
<role>lead</role>
<name>Chuck Hagenbuch</name>
<email>chuck at horde.org</email>
</maintainer>
</maintainers>
<release>
<version>0.0.1</version>
<state>alpha</state>
<date>2004-01-25</date>
<notes>Initial Release</notes>
<filelist>
<file baseinstalldir="/Horde" role="php" name="History.php" />
</filelist>
<provides type="class" name="Horde_History" />
</release>
<changelog>
<release>
<version>0.0.1</version>
<state>alpha</state>
<date>2004-01-25</date>
<notes>Initial release as a PEAR package</notes>
</release>
</changelog>
</package>
More information about the commits
mailing list