[ Index ]
 

Code source de Horde 3.1.3

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/lib/Horde/ -> History.php (source)

   1  <?php
   2  /**
   3   * The History:: class provides a method of tracking changes in Horde
   4   * objects, stored in a SQL table.
   5   *
   6   * $Horde: framework/History/History.php,v 1.28.2.14 2006/05/03 21:46:13 jan Exp $
   7   *
   8   * Copyright 2003-2006 Chuck Hagenbuch <chuck@horde.org>
   9   *
  10   * See the enclosed file COPYING for license information (LGPL). If you
  11   * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
  12   *
  13   * @author  Chuck Hagenbuch <chuck@horde.org>
  14   * @since   Horde 2.1
  15   * @package Horde_History
  16   */
  17  class Horde_History {
  18  
  19      /**
  20       * Pointer to a DB instance to manage the history.
  21       *
  22       * @var DB
  23       */
  24      var $_db;
  25  
  26      /**
  27       * Attempts to return a reference to a concrete History instance.
  28       * It will only create a new instance if no History instance
  29       * currently exists.
  30       *
  31       * This method must be invoked as: $var = &History::singleton()
  32       *
  33       * @return Horde_History  The concrete History reference, or false on an
  34       *                        error.
  35       */
  36      function &singleton()
  37      {
  38          static $history;
  39  
  40          if (!isset($history)) {
  41              $history = &new Horde_History();
  42          }
  43  
  44          return $history;
  45      }
  46  
  47      /**
  48       * Constructor.
  49       */
  50      function Horde_History()
  51      {
  52          global $conf;
  53  
  54          if (empty($conf['sql'])) {
  55              $this->_db = PEAR::raiseError(_("The History system is disabled."));
  56          }
  57  
  58          require_once 'DB.php';
  59          $this->_db = &DB::connect($conf['sql']);
  60  
  61          /* Set DB portability options. */
  62          if (is_a($this->_db, 'DB_common')) {
  63              switch ($this->_db->phptype) {
  64              case 'mssql':
  65                  $this->_db->setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS | DB_PORTABILITY_RTRIM);
  66                  break;
  67              default:
  68                  $this->_db->setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS);
  69              }
  70          }
  71      }
  72  
  73      /**
  74       * Logs an event to an item's history log. The item must be uniquely
  75       * identified by $guid. Any other details about the event are passed in
  76       * $attributes. Standard suggested attributes are:
  77       *
  78       *   'who' => The id of the user that performed the action (will be added
  79       *            automatically if not present).
  80       *
  81       *   'ts' => Timestamp of the action (this will be added automatically if
  82       *           it is not present).
  83       *
  84       * @param string $guid            The unique identifier of the entry to
  85       *                                add to.
  86       * @param array $attributes       The hash of name => value entries that
  87       *                                describe this event.
  88       * @param boolean $replaceAction  If $attributes['action'] is already
  89       *                                present in the item's history log,
  90       *                                update that entry instead of creating a
  91       *                                new one.
  92       *
  93       * @return boolean|PEAR_Error  True on success, PEAR_Error on failure.
  94       */
  95      function log($guid, $attributes = array(), $replaceAction = false)
  96      {
  97          if (is_a($this->_db, 'PEAR_Error')) {
  98              return $this->_db;
  99          }
 100  
 101          $history = &$this->getHistory($guid);
 102          if (!$history || is_a($history, 'PEAR_Error')) {
 103              return $history;
 104          }
 105  
 106          if (empty($attributes['who'])) {
 107              $attributes['who'] = Auth::getAuth();
 108          }
 109          if (empty($attributes['ts'])) {
 110              $attributes['ts'] = time();
 111          }
 112  
 113          /* If we want to replace an entry with the same action, try and find
 114           * one. Track whether or not we succeed in $done, so we know whether
 115           * or not to add the entry later. */
 116          $done = false;
 117          if ($replaceAction && !empty($attributes['action'])) {
 118              $count = count($history->data);
 119              for ($i = 0; $i < $count; $i++) {
 120                  if (!empty($history->data[$i]['action']) &&
 121                      $history->data[$i]['action'] == $attributes['action']) {
 122  
 123                      $values = array($attributes['ts'],
 124                                      $attributes['who'],
 125                                      isset($attributes['desc']) ? $attributes['desc'] : null);
 126                      unset($attributes['ts']);
 127                      unset($attributes['who']);
 128                      unset($attributes['desc']);
 129                      unset($attributes['action']);
 130                      if ($attributes) {
 131                          $values[] = serialize($attributes);
 132                      } else {
 133                          $values[] = null;
 134                      }
 135                      $values[] = $history->data[$i]['id'];
 136  
 137                      $r = $this->_db->query('UPDATE horde_histories SET history_ts = ?,' .
 138                                        ' history_who = ?,' .
 139                                        ' history_desc = ?,' .
 140                                        ' history_extra = ? WHERE history_id = ?', $values);
 141                      if (is_a($r, 'PEAR_Error')) {
 142                          return $r;
 143                      }
 144                      $done = true;
 145                      break;
 146                  }
 147              }
 148          }
 149  
 150          /* If we're not replacing by action, or if we didn't find an entry to
 151           * replace, insert a new row. */
 152          if (!$done) {
 153              $values = array($this->_db->nextId('horde_histories'),
 154                              $guid,
 155                              $attributes['ts'],
 156                              $attributes['who'],
 157                              isset($attributes['desc']) ? $attributes['desc'] : null,
 158                              isset($attributes['action']) ? $attributes['action'] : null);
 159              unset($attributes['ts']);
 160              unset($attributes['who']);
 161              unset($attributes['desc']);
 162              unset($attributes['action']);
 163              if ($attributes) {
 164                  $values[] = serialize($attributes);
 165              } else {
 166                  $values[] = null;
 167              }
 168  
 169              $r = $this->_db->query('INSERT INTO horde_histories (history_id, object_uid, history_ts, history_who, history_desc, history_action, history_extra)' .
 170                                ' VALUES (?, ?, ?, ?, ?, ?, ?)', $values);
 171              if (is_a($r, 'PEAR_Error')) {
 172                  return $r;
 173              }
 174          }
 175  
 176          return true;
 177      }
 178  
 179      /**
 180       * Returns a HistoryObject corresponding to the named history
 181       * entry, with the data retrieved appropriately. $autocreate has
 182       * no affect.
 183       *
 184       * @param string $guid         The name of the history entry to retrieve.
 185       * @param boolean $autocreate  Deprecated.
 186       */
 187      function &getHistory($guid, $autocreate = null)
 188      {
 189          if (is_a($this->_db, 'PEAR_Error')) {
 190              $false = false;
 191              return $false;
 192          }
 193  
 194          $rows = $this->_db->getAll('SELECT * FROM horde_histories WHERE object_uid = ?', array($guid), DB_FETCHMODE_ASSOC);
 195          $history = &new HistoryObject($guid, $rows);
 196          return $history;
 197      }
 198  
 199      /**
 200       * Finds history objects by timestamp, and optionally filter on other
 201       * fields as well.
 202       *
 203       * @param string $cmp     The comparison operator (<, >, <=, >=, or =) to
 204       *                        check the timestamps with.
 205       * @param integer $ts     The timestamp to compare against.
 206       * @param array $filters  An array of additional (ANDed) criteria.
 207       *                        Each array value should be an array with 3
 208       *                        entries:
 209       * <pre>
 210       *                         'op'    - the operator to compare this field
 211       *                                   with.
 212       *                         'field' - the history field being compared
 213       *                                   (i.e. 'action').
 214       *                         'value' - the value to check for (i.e. 'add').
 215       * </pre>
 216       * @param string $parent  The parent history to start searching at. If non-empty,
 217       *                        will be searched for with a LIKE '$parent:%' clause.
 218       *
 219       * @return array  An array of history object ids, or an empty array if
 220       *                none matched the criteria.
 221       */
 222      function getByTimestamp($cmp, $ts, $filters = array(), $parent = null)
 223      {
 224          if (is_a($this->_db, 'PEAR_Error')) {
 225              return false;
 226          }
 227  
 228          /* Build the timestamp test. */
 229          $where = array("history_ts $cmp $ts");
 230  
 231          /* Add additional filters, if there are any. */
 232          if ($filters) {
 233              foreach ($filters as $filter) {
 234                  $where[] = 'history_' . $filter['field'] . ' ' . $filter['op'] . ' ' . $this->_db->quote($filter['value']);
 235              }
 236          }
 237  
 238          if ($parent) {
 239              $where[] = 'object_uid LIKE ' . $this->_db->quote($parent . ':%');
 240          }
 241  
 242          return $this->_db->getAssoc('SELECT DISTINCT object_uid, history_id FROM horde_histories WHERE ' . implode(' AND ', $where));
 243      }
 244  
 245      /**
 246       * Gets the timestamp of the most recent change to $guid.
 247       *
 248       * @param string $guid    The name of the history entry to retrieve.
 249       * @param string $action  An action: 'add', 'modify', 'delete', etc.
 250       *
 251       * @return integer  The timestamp, or 0 if no matching entry is found.
 252       */
 253      function getActionTimestamp($guid, $action)
 254      {
 255          /* This implementation still works, but we should be able to
 256           * get much faster now with a SELECT MAX(history_ts)
 257           * ... query. */
 258          $history = &$this->getHistory($guid);
 259          if (!$history || is_a($history, 'PEAR_Error')) {
 260              return 0;
 261          }
 262  
 263          $last = 0;
 264          if (is_array($history->data)) {
 265              foreach ($history->data as $entry) {
 266                  if ($entry['action'] == $action && $entry['ts'] > $last) {
 267                      $last = $entry['ts'];
 268                  }
 269              }
 270          }
 271  
 272          return $last;
 273      }
 274  
 275      /**
 276       * Remove one or more history entries by name.
 277       *
 278       * @param array $names  The history entries to remove.
 279       */
 280      function removeByNames($names)
 281      {
 282          if (is_a($this->_db, 'PEAR_Error')) {
 283              return false;
 284          }
 285  
 286          $ids = array();
 287          foreach ($names as $name) {
 288              $ids[] = $this->_db->quote($name);
 289          }
 290  
 291          return $this->_db->query('DELETE FROM horde_histories WHERE object_uid IN (' . implode(',', $ids) . ')');
 292      }
 293  
 294  }
 295  
 296  /**
 297   * Class for presenting History information.
 298   *
 299   * @author  Chuck Hagenbuch <chuck@horde.org>
 300   * @since   Horde 2.1
 301   * @package Horde_History
 302   */
 303  class HistoryObject {
 304  
 305      var $uid;
 306      var $data = array();
 307  
 308      function HistoryObject($uid, $data = array())
 309      {
 310          $this->uid = $uid;
 311  
 312          if (!$data || is_a($data, 'PEAR_Error')) {
 313              return;
 314          }
 315  
 316          foreach ($data as $row) {
 317              $history = array('action' => $row['history_action'],
 318                               'desc' => $row['history_desc'],
 319                               'who' => $row['history_who'],
 320                               'id' => $row['history_id'],
 321                               'ts' => $row['history_ts']);
 322              if ($row['history_extra']) {
 323                  $extra = @unserialize($row['history_extra']);
 324                  if ($extra) {
 325                      $history = array_merge($history, $extra);
 326                  }
 327              }
 328              $this->data[] = $history;
 329          }
 330      }
 331  
 332      function getData()
 333      {
 334          return $this->data;
 335      }
 336  
 337  }


Généré le : Sun Feb 25 18:01:28 2007 par Balluche grâce à PHPXref 0.7