Overview

Packages

  • History

Classes

  • Horde_History
  • Horde_History_Exception
  • Horde_History_Log
  • Horde_History_Mock
  • Horde_History_Sql
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * A SQL based history driver.
  4:  *
  5:  * PHP version 5
  6:  *
  7:  * @category Horde
  8:  * @package  History
  9:  * @author   Chuck Hagenbuch <chuck@horde.org>
 10:  * @license  http://www.horde.org/licenses/lgpl21 LGPL 2.1
 11:  * @link     http://pear.horde.org/index.php?package=History
 12:  */
 13: 
 14: /**
 15:  * The Horde_History_Sql:: class provides a method of tracking changes in
 16:  * Horde objects, stored in a SQL table.
 17:  *
 18:  * Copyright 2003-2012 Horde LLC (http://www.horde.org/)
 19:  *
 20:  * See the enclosed file COPYING for license information (LGPL). If you
 21:  * did not receive this file, see http://www.horde.org/licenses/lgpl21.
 22:  *
 23:  * @category Horde
 24:  * @package  History
 25:  * @author   Chuck Hagenbuch <chuck@horde.org>
 26:  * @license  http://www.horde.org/licenses/lgpl21 LGPL 2.1
 27:  * @link     http://pear.horde.org/index.php?package=History
 28:  */
 29: class Horde_History_Sql extends Horde_History
 30: {
 31:     /**
 32:      * Horde_Db_Adapter instance to manage the history.
 33:      *
 34:      * @var Horde_Db_Adapter
 35:      */
 36:     protected $_db;
 37: 
 38:     /**
 39:      * Constructor.
 40:      *
 41:      * @param string $auth  The current user.
 42:      * @param Horde_Db_Adapter $db  The database connection.
 43:      */
 44:     public function __construct($auth, Horde_Db_Adapter $db)
 45:     {
 46:         parent::__construct($auth);
 47:         $this->_db = $db;
 48:     }
 49: 
 50:     /**
 51:      * Gets the timestamp of the most recent change to $guid.
 52:      *
 53:      * @param string $guid   The name of the history entry to retrieve.
 54:      * @param string $action An action: 'add', 'modify', 'delete', etc.
 55:      *
 56:      * @return integer  The timestamp, or 0 if no matching entry is found.
 57:      *
 58:      * @throws Horde_History_Exception If the input parameters are not of type string.
 59:      */
 60:     public function getActionTimestamp($guid, $action)
 61:     {
 62:         if (!is_string($guid) || !is_string($action)) {
 63:             throw new Horde_History_Exception('$guid and $action need to be strings!');
 64:         }
 65: 
 66:         try {
 67:             $result = $this->_db->selectValue('SELECT MAX(history_ts) FROM horde_histories WHERE history_action = ? AND object_uid = ?', array($action, $guid));
 68:         } catch (Horde_Db_Exception $e) {
 69:             return 0;
 70:         }
 71: 
 72:         return (int)$result;
 73:     }
 74: 
 75:     /**
 76:      * Logs an event to an item's history log. Any other details about the
 77:      * event are passed in $attributes.
 78:      *
 79:      * @param Horde_History_Log $history       The history item to add to.
 80:      * @param array             $attributes    The hash of name => value
 81:      *                                         entries that describe this
 82:      *                                         event.
 83:      * @param boolean           $replaceAction If $attributes['action'] is
 84:      *                                         already present in the item's
 85:      *                                         history log, update that entry
 86:      *                                         instead of creating a new one.
 87:      *
 88:      * @throws Horde_History_Exception
 89:      */
 90:     protected function _log(Horde_History_Log $history, array $attributes,
 91:                             $replaceAction = false)
 92:     {
 93:         /* If we want to replace an entry with the same action, try and find
 94:          * one. Track whether or not we succeed in $done, so we know whether or
 95:          * not to add the entry later. */
 96:         $done = false;
 97:         if ($replaceAction && !empty($attributes['action'])) {
 98:             foreach ($history as $entry) {
 99:                 if (!empty($entry['action']) &&
100:                     $entry['action'] == $attributes['action']) {
101:                     $values = array(
102:                         $attributes['ts'],
103:                         $attributes['who'],
104:                         isset($attributes['desc']) ? $attributes['desc'] : null
105:                     );
106: 
107:                     unset($attributes['ts'], $attributes['who'], $attributes['desc'], $attributes['action']);
108: 
109:                     $values[] = $attributes
110:                         ? serialize($attributes)
111:                         : null;
112:                     $values[] = $entry['id'];
113: 
114:                     try {
115:                         $r = $this->_db->update(
116:                             'UPDATE horde_histories SET history_ts = ?,' .
117:                             ' history_who = ?,' .
118:                             ' history_desc = ?,' .
119:                             ' history_extra = ? WHERE history_id = ?', $values
120:                         );
121:                     } catch (Horde_Db_Exception $e) {
122:                         throw new Horde_History_Exception($e);
123:                     }
124: 
125:                     $done = true;
126:                     break;
127:                 }
128:             }
129:         }
130: 
131:         /* If we're not replacing by action, or if we didn't find an entry to
132:          * replace, insert a new row. */
133:         if (!$done) {
134:             $values = array(
135:                 $history->uid,
136:                 $attributes['ts'],
137:                 $attributes['who'],
138:                 isset($attributes['desc']) ? $attributes['desc'] : null,
139:                 isset($attributes['action']) ? $attributes['action'] : null
140:             );
141: 
142:             unset($attributes['ts'], $attributes['who'], $attributes['desc'], $attributes['action']);
143: 
144:             $values[] = $attributes
145:                 ? serialize($attributes)
146:                 : null;
147: 
148:             try {
149:                 $this->_db->insert(
150:                     'INSERT INTO horde_histories (object_uid, history_ts, history_who, history_desc, history_action, history_extra)' .
151:                     ' VALUES (?, ?, ?, ?, ?, ?)', $values
152:                 );
153:             } catch (Horde_Db_Exception $e) {
154:                 throw new Horde_History_Exception($e);
155:             }
156:         }
157:     }
158: 
159:     /**
160:      * Returns a Horde_History_Log corresponding to the named history entry,
161:      * with the data retrieved appropriately.
162:      *
163:      * @param string $guid The name of the history entry to retrieve.
164:      *
165:      * @return Horde_History_Log  A Horde_History_Log object.
166:      *
167:      * @throws Horde_History_Exception
168:      */
169:     public function _getHistory($guid)
170:     {
171:         $rows = $this->_db->selectAll('SELECT * FROM horde_histories WHERE object_uid = ?', array($guid));
172:         return new Horde_History_Log($guid, $rows);
173:     }
174: 
175:     /**
176:      * Finds history objects by timestamp, and optionally filter on other
177:      * fields as well.
178:      *
179:      * @param string  $cmp     The comparison operator (<, >, <=, >=, or =) to
180:      *                         check the timestamps with.
181:      * @param integer $ts      The timestamp to compare against.
182:      * @param array   $filters An array of additional (ANDed) criteria.
183:      *                         Each array value should be an array with 3
184:      *                         entries:
185:      *                         - field: the history field being compared (i.e.
186:      *                           'action').
187:      *                         - op: the operator to compare this field with.
188:      *                         - value: the value to check for (i.e. 'add').
189:      * @param string  $parent  The parent history to start searching at. If
190:      *                         non-empty, will be searched for with a LIKE
191:      *                         '$parent:%' clause.
192:      *
193:      * @return array  An array of history object ids, or an empty array if
194:      *                none matched the criteria.
195:      *
196:      * @throws Horde_History_Exception
197:      */
198:     public function _getByTimestamp($cmp, $ts, array $filters = array(),
199:                                     $parent = null)
200:     {
201:         /* Build the timestamp test. */
202:         $where = array("history_ts $cmp $ts");
203: 
204:         /* Add additional filters, if there are any. */
205:         if ($filters) {
206:             foreach ($filters as $filter) {
207:                 $where[] = 'history_' . $filter['field'] . ' ' . $filter['op'] . ' ' . $this->_db->quote($filter['value']);
208:             }
209:         }
210: 
211:         if ($parent) {
212:             $where[] = 'object_uid LIKE ' . $this->_db->quote($parent . ':%');
213:         }
214: 
215:         return $this->_db->selectAssoc('SELECT DISTINCT object_uid, history_id FROM horde_histories WHERE ' . implode(' AND ', $where));
216:     }
217: 
218:     /**
219:      * Removes one or more history entries by name.
220:      *
221:      * @param array $names  The history entries to remove.
222:      *
223:      * @throws Horde_History_Exception
224:      */
225:     public function removeByNames(array $names)
226:     {
227:         if (!count($names)) {
228:             return;
229:         }
230: 
231:         $ids = array();
232:         foreach ($names as $name) {
233:             $ids[] = $this->_db->quote($name);
234:         }
235: 
236:         $this->_db->delete('DELETE FROM horde_histories WHERE object_uid IN (' . implode(',', $ids) . ')');
237:     }
238: }
239: 
API documentation generated by ApiGen