ILIAS  release_4-3 Revision
 All Data Structures Namespaces Files Functions Variables Groups Pages
mdb2.php
Go to the documentation of this file.
1 <?php
10 require_once 'MDB2.php';
11 MDB2::loadFile('Date');
12 
34 class Log_mdb2 extends Log
35 {
41  var $_dsn = '';
42 
48  var $_options = array('persistent' => true);
49 
55  var $_db = null;
56 
62  var $_statement = null;
63 
69  var $_existingConnection = false;
70 
76  var $_table = 'log_table';
77 
83  var $_sequence = 'log_id';
84 
91  var $_identLimit = 16;
92 
98  var $_types = array(
99  'id' => 'integer',
100  'logtime' => 'timestamp',
101  'ident' => 'text',
102  'priority' => 'text',
103  'message' => 'clob'
104  );
105 
115  function Log_mdb2($name, $ident = '', $conf = array(),
116  $level = PEAR_LOG_DEBUG)
117  {
118  $this->_id = md5(microtime());
119  $this->_table = $name;
120  $this->_mask = Log::UPTO($level);
121 
122  /* If an options array was provided, use it. */
123  if (isset($conf['options']) && is_array($conf['options'])) {
124  $this->_options = $conf['options'];
125  }
126 
127  /* If a specific sequence name was provided, use it. */
128  if (!empty($conf['sequence'])) {
129  $this->_sequence = $conf['sequence'];
130  }
131 
132  /* If a specific sequence name was provided, use it. */
133  if (isset($conf['identLimit'])) {
134  $this->_identLimit = $conf['identLimit'];
135  }
136 
137  /* Now that the ident limit is confirmed, set the ident string. */
138  $this->setIdent($ident);
139 
140  /* If an existing database connection was provided, use it. */
141  if (isset($conf['db'])) {
142  $this->_db = &$conf['db'];
143  $this->_existingConnection = true;
144  $this->_opened = true;
145  } elseif (isset($conf['singleton'])) {
146  $this->_db = &MDB2::singleton($conf['singleton'], $this->_options);
147  $this->_existingConnection = true;
148  $this->_opened = true;
149  } else {
150  $this->_dsn = $conf['dsn'];
151  }
152  }
153 
161  function open()
162  {
163  if (!$this->_opened) {
164  /* Use the DSN and options to create a database connection. */
165  $this->_db = &MDB2::connect($this->_dsn, $this->_options);
166  if (PEAR::isError($this->_db)) {
167  return false;
168  }
169 
170  /* Create a prepared statement for repeated use in log(). */
171  if (!$this->_prepareStatement()) {
172  return false;
173  }
174 
175  /* We now consider out connection open. */
176  $this->_opened = true;
177  }
178 
179  return $this->_opened;
180  }
181 
190  function close()
191  {
192  /* If we have a statement object, free it. */
193  if (is_object($this->_statement)) {
194  $this->_statement->free();
195  $this->_statement = null;
196  }
197 
198  /* If we opened the database connection, disconnect it. */
199  if ($this->_opened && !$this->_existingConnection) {
200  $this->_opened = false;
201  return $this->_db->disconnect();
202  }
203 
204  return ($this->_opened === false);
205  }
206 
217  function setIdent($ident)
218  {
219  $this->_ident = substr($ident, 0, $this->_identLimit);
220  }
221 
235  function log($message, $priority = null)
236  {
237  /* If a priority hasn't been specified, use the default value. */
238  if ($priority === null) {
239  $priority = $this->_priority;
240  }
241 
242  /* Abort early if the priority is above the maximum logging level. */
243  if (!$this->_isMasked($priority)) {
244  return false;
245  }
246 
247  /* If the connection isn't open and can't be opened, return failure. */
248  if (!$this->_opened && !$this->open()) {
249  return false;
250  }
251 
252  /* If we don't already have a statement object, create one. */
253  if (!is_object($this->_statement) && !$this->_prepareStatement()) {
254  return false;
255  }
256 
257  /* Extract the string representation of the message. */
258  $message = $this->_extractMessage($message);
259 
260  /* Build our set of values for this log entry. */
261  $values = array(
262  'id' => $this->_db->nextId($this->_sequence),
263  'logtime' => MDB2_Date::mdbNow(),
264  'ident' => $this->_ident,
265  'priority' => $priority,
266  'message' => $message
267  );
268 
269  /* Execute the SQL query for this log entry insertion. */
270  $this->_db->expectError(MDB2_ERROR_NOSUCHTABLE);
271  $result = &$this->_statement->execute($values);
272  $this->_db->popExpect();
273 
274  /* Attempt to handle any errors. */
275  if (PEAR::isError($result)) {
276  /* We can only handle MDB2_ERROR_NOSUCHTABLE errors. */
277  if ($result->getCode() != MDB2_ERROR_NOSUCHTABLE) {
278  return false;
279  }
280 
281  /* Attempt to create the target table. */
282  if (!$this->_createTable()) {
283  return false;
284  }
285 
286  /* Recreate our prepared statement resource. */
287  $this->_statement->free();
288  if (!$this->_prepareStatement()) {
289  return false;
290  }
291 
292  /* Attempt to re-execute the insertion query. */
293  $result = $this->_statement->execute($values);
294  if (PEAR::isError($result)) {
295  return false;
296  }
297  }
298 
299  $this->_announce(array('priority' => $priority, 'message' => $message));
300 
301  return true;
302  }
303 
310  function _createTable()
311  {
312  $this->_db->loadModule('Manager', null, true);
313  $result = $this->_db->manager->createTable(
314  $this->_table,
315  array(
316  'id' => array('type' => $this->_types['id']),
317  'logtime' => array('type' => $this->_types['logtime']),
318  'ident' => array('type' => $this->_types['ident']),
319  'priority' => array('type' => $this->_types['priority']),
320  'message' => array('type' => $this->_types['message'])
321  )
322  );
323  if (PEAR::isError($result)) {
324  return false;
325  }
326 
327  $result = $this->_db->manager->createIndex(
328  $this->_table,
329  'unique_id',
330  array('fields' => array('id' => true), 'unique' => true)
331  );
332  if (PEAR::isError($result)) {
333  return false;
334  }
335 
336  return true;
337  }
338 
347  function _prepareStatement()
348  {
349  $this->_statement = &$this->_db->prepare(
350  'INSERT INTO ' . $this->_table .
351  ' (id, logtime, ident, priority, message)' .
352  ' VALUES(:id, :logtime, :ident, :priority, :message)',
353  $this->_types, MDB2_PREPARE_MANIP);
354 
355  /* Return success if we didn't generate an error. */
356  return (PEAR::isError($this->_statement) === false);
357  }
358 }