PageRenderTime 43ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/db/db.class.php

https://bitbucket.org/Daniel0203/openrat
PHP | 489 lines | 255 code | 95 blank | 139 comment | 10 complexity | 9e2d7918201627b98e3954e2c53987a1 MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. //
  3. // +----------------------------------------------------------------------+
  4. // | PHP version 4.0 |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2001 The PHP Group |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.02 of the PHP license, |
  9. // | that is bundled with this package in the file LICENSE, and is |
  10. // | available at through the world-wide-web at |
  11. // | http://www.php.net/license/2_02.txt. |
  12. // | If you did not receive a copy of the PHP license and are unable to |
  13. // | obtain it through the world-wide-web, please send a note to |
  14. // | license@php.net so we can mail you a copy immediately. |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Stig Bakken <ssb@fast.no> |
  17. // | Jan Dankert <phpdb@jandankert.de> |
  18. // +----------------------------------------------------------------------+
  19. //
  20. // This is the database abstraction layer. This class was inspired by the
  21. // PHP-Pear-DB package. Thanks to its developers.
  22. /**
  23. * Darstellung einer Datenbank-Verbindung.
  24. * F�r die echten DB-Aufrufe werden die entsprechenden
  25. * Methoden des passenden Clients aufgerufen.
  26. *
  27. * Diese Klasse stammt urspruenglich aus dem PHP-Pear-DB-Projekt und unterliegt
  28. * daher auch der PHP-licence.
  29. *
  30. * @author Jan Dankert
  31. * @package openrat.database
  32. */
  33. class DB
  34. {
  35. /**
  36. * Datenbank-Id.
  37. *
  38. * @var String
  39. */
  40. var $id;
  41. /**
  42. * Konfiguration der Datenbank-Verbindung
  43. *
  44. * @var Array
  45. */
  46. var $conf;
  47. /**
  48. * Kennzeichen, ob die Datenbank verf�gbar ist.
  49. *
  50. * @var Boolean
  51. */
  52. var $available;
  53. /**
  54. * Enth�lt eine Fehlermeldung (sofern verf�gbar).
  55. *
  56. * @var String
  57. */
  58. var $error;
  59. /**
  60. * Client.
  61. * Enth�lt ein Objekt der Klasse db_<type>.
  62. *
  63. * @var Object
  64. */
  65. var $client;
  66. /**
  67. * Schalter, ob eine Transaktion begonnen wurde.
  68. * @var boolean
  69. */
  70. var $transactionInProgress = false;
  71. /**
  72. * Kontruktor.
  73. * Erwartet die Datenbank-Konfiguration als Parameter.
  74. *
  75. * @param Array Konfiguration der Verbindung
  76. * @return Status 'true' wenn Verbindung erfolgreich aufgebaut.
  77. */
  78. public function DB( $conf )
  79. {
  80. $this->available = false;
  81. $this->conf = $conf;
  82. $this->connect();
  83. return $this->available;
  84. }
  85. /**
  86. * Verbindung zur Datenbank aufbauen.
  87. *
  88. * @return Status
  89. */
  90. public function connect()
  91. {
  92. // Ausfuehren des Systemkommandos vor Verbindungsaufbau
  93. if ( !empty($this->conf['cmd']))
  94. {
  95. $ausgabe = array();
  96. $rc = false;
  97. Logger::debug("Database command executing: ".$this->conf['cmd']);
  98. exec( $this->conf['cmd'],$ausgabe,$rc );
  99. foreach( $ausgabe as $zeile )
  100. Logger::debug("Database command output: ".$zeile);
  101. if ( $rc != 0 )
  102. {
  103. $this->error = 'Command failed: '.implode("",$ausgabe);
  104. $this->available = false;
  105. return false;
  106. }
  107. }
  108. $type = $this->conf['type'];
  109. $classname = 'db_'.$type;
  110. if ( ! class_exists($classname) )
  111. {
  112. $this->error = 'Database type "'.$type.'" is not available';
  113. $this->available = false;
  114. return false;
  115. }
  116. // Client instanziieren
  117. $this->client = & new $classname;
  118. $ok = $this->client->connect( $this->conf );
  119. if ( ! $ok )
  120. {
  121. $this->error = 'Cannot connect to database: '.$this->client->error;
  122. $this->available = false;
  123. return false;
  124. }
  125. // SQL nach Verbindungsaufbau ausfuehren.
  126. if ( isset($this->conf['connection_sql']) && ! empty($this->conf['connection_sql']) )
  127. {
  128. $cmd = $this->conf['connection_sql'];
  129. $ok = $this->client->query($cmd);
  130. if ( ! $ok )
  131. {
  132. $this->error = $this->client->error;
  133. $this->available = false;
  134. return false;
  135. }
  136. }
  137. $this->available = true;
  138. return true;
  139. }
  140. /**
  141. * Ausfuehren einer Datenbankanfrage.
  142. *
  143. * @param SQL-Objekt
  144. * @return Object (Result)
  145. */
  146. public function query( $query )
  147. {
  148. if ( !is_object($query) )
  149. die('SQL-Query must be an object');
  150. // Vorbereitete Datenbankabfrage ("Prepared Statement")
  151. if ( isset($this->conf['prepare']) && $this->conf['prepare'] )
  152. {
  153. $this->client->clear();
  154. // Statement an die Datenbank schicken
  155. $this->client->prepare( $query->raw,$query->param );
  156. // Einzelne Parameter an die Anfrage binden
  157. foreach ($query->param as $name=>$unused)
  158. $this->client->bind($name,$this->convertCharsetToDatabase($query->data[$name]));
  159. // Ausf�hren...
  160. $result = $this->client->query($query);
  161. if ( $result === FALSE )
  162. {
  163. $this->error = $this->client->error;
  164. Logger::warn('Database error: '.$this->error);
  165. Http::serverError('Database Error',$this->error);
  166. }
  167. return $result;
  168. }
  169. else
  170. {
  171. // Es handelt sich um eine nicht-vorbereitete Anfrage. Das gesamte
  172. // SQL wird durch die SQL-Klasse erzeugt, dort werden auch die Parameter
  173. // in die Abfrage gesetzt.
  174. $escape_function = method_exists($this->client,'escape')?$this->client->escape():'addslashes';
  175. $flatQuery = $query->getQuery( $escape_function );
  176. $flatQuery = $this->convertCharsetToDatabase($flatQuery);
  177. Logger::trace('DB query on DB '.$this->id."\n".$query->raw);
  178. $result = $this->client->query($flatQuery);
  179. if ( $result === FALSE )
  180. {
  181. $this->error = $this->client->error;
  182. if ( true )
  183. {
  184. Logger::warn('Database error: '.$this->error);
  185. Http::serverError('Database Error',$this->error);
  186. }
  187. }
  188. if ( isset($this->conf['autocommit']) && @$this->conf['autocommit'])
  189. if ( method_exists($this->client,'commit') )
  190. $this->client->commit();
  191. return $result;
  192. }
  193. }
  194. /**
  195. * Ermittelt genau 1 Datenbankergebnis aus einer SQL-Anfrage.
  196. * Falls es mehrere Treffer gibt, wird die 1. Spalte aus der 1. Zeile genommen.
  197. *
  198. * @param String $query
  199. * @return String
  200. */
  201. public function &getOne( $query )
  202. {
  203. $none = '';
  204. $result = $this->query($query);
  205. $row = $this->client->fetchRow( $result,0 );
  206. $this->client->freeResult($result);
  207. if ( ! is_array($row) )
  208. return $none;
  209. array_walk($row,array($this,'convertCharsetFromDatabase'));
  210. $keys = array_keys($row);
  211. return $row[ $keys[0] ];
  212. }
  213. /**
  214. * Ermittelt eine Zeile aus der Datenbank.
  215. *
  216. * @param String $query
  217. * @return Array
  218. */
  219. public function &getRow( $query )
  220. {
  221. $result = $this->query($query);
  222. if ( $result === FALSE )
  223. {
  224. $this->error = $this->client->error;
  225. Logger::warn('Database error: '.$this->error);
  226. Http::serverError('Database Error',$this->error);
  227. }
  228. $row = $this->client->fetchRow( $result,0 );
  229. $this->client->freeResult($result);
  230. if ( ! is_array($row) )
  231. $row = array();
  232. //Html::debug($row,"vorher");
  233. $row = $this->convertRowWithCharsetFromDatabase($row);
  234. //Html::debug($row,"nachher");
  235. return $row;
  236. }
  237. /**
  238. * Ermittelt eine (die 1.) Spalte aus dem Datenbankergebnis.
  239. *
  240. * @param String $query
  241. * @return Array
  242. */
  243. public function &getCol( $query )
  244. {
  245. $result = $this->query($query);
  246. $i = 0;
  247. $col = array();
  248. while( $row = $this->client->fetchRow( $result,$i++ ) )
  249. {
  250. if ( empty($row) )
  251. break;
  252. array_walk($row,array($this,'convertCharsetFromDatabase'));
  253. $keys = array_keys($row);
  254. $col[] = $row[ $keys[0] ];
  255. }
  256. $this->client->freeResult($result);
  257. return $col;
  258. }
  259. /**
  260. * Ermittelt ein assoziatives Array aus der Datenbank.
  261. *
  262. * @param String $query
  263. * @param Boolean $force_array
  264. * @return Array
  265. */
  266. public function &getAssoc( $query, $force_array = false )
  267. {
  268. $results = array();
  269. $result = $this->query($query);
  270. $i = 0;
  271. while( $row = $this->client->fetchRow( $result,$i++ ) )
  272. {
  273. if ( empty($row) )
  274. break;
  275. array_walk($row,array($this,'convertCharsetFromDatabase'));
  276. if ( count($row) > 2 || $force_array )
  277. {
  278. // FIXME: Wird offenbar nie ausgeführt.
  279. $row = $res->fetchRow($i);
  280. $keys = array_keys($row);
  281. $key1 = $keys[0];
  282. unset( $row[$key1] );
  283. $results[ $row[$key1] ] = $row;
  284. }
  285. else
  286. {
  287. $keys = array_keys($row);
  288. $key1 = $keys[0];
  289. $key2 = $keys[1];
  290. $results[ $row[$key1] ] = $row[$key2];
  291. }
  292. }
  293. $this->client->freeResult( $result );
  294. return $results;
  295. }
  296. /**
  297. * Ermittelt alle Datenbankergebniszeilen.
  298. *
  299. * @param String $query
  300. * @return Array
  301. */
  302. public function &getAll( $query )
  303. {
  304. $result = $this->query( $query );
  305. $results = array();
  306. $i = 0;
  307. while( $row = $this->client->fetchRow( $result,$i++ ) )
  308. {
  309. array_walk($row,array($this,'convertCharsetFromDatabase'));
  310. $results[] = $row;
  311. }
  312. $this->client->freeResult( $result );
  313. return $results;
  314. }
  315. /**
  316. * Startet eine Transaktion.
  317. */
  318. public function start()
  319. {
  320. if ( @$this->conf['transaction'])
  321. if ( method_exists($this->client,'start') )
  322. {
  323. $this->transactionInProgress = true;
  324. $this->client->start();
  325. }
  326. }
  327. /**
  328. * Beendet und best�tigt eine Transaktion.
  329. */
  330. public function commit()
  331. {
  332. if ( @$this->conf['transaction'])
  333. if ( method_exists($this->client,'commit') )
  334. if ( $this->transactionInProgress )
  335. {
  336. $this->client->commit();
  337. $this->transactionInProgress = false;
  338. }
  339. }
  340. /**
  341. * Setzt eine Transaktion zur�ck.
  342. */
  343. public function rollback()
  344. {
  345. if ( @$this->conf['transaction'])
  346. if ( method_exists($this->client,'rollback') )
  347. if ( $this->transactionInProgress )
  348. {
  349. $this->client->rollback();
  350. $this->transactionInProgress = false;
  351. }
  352. }
  353. private function convertCharsetToDatabase($text)
  354. {
  355. //Logger::debug('from '.$text);
  356. $dbCharset = @$this->conf['charset'];
  357. if ( !empty($dbCharset) && $dbCharset != 'UTF-8' )
  358. {
  359. // Logger::debug('Converting from UTF-8 to '.$dbCharset);
  360. if ( !function_exists('iconv') )
  361. Logger::warn('iconv not available - database charset unchanged. Please '.
  362. 'enable iconv on your system or transform your database content to UTF-8.');
  363. else
  364. $text = iconv('UTF-8',$dbCharset.'//TRANSLIT',$text);
  365. }
  366. //Logger::debug('to '.$text);
  367. return $text;
  368. }
  369. private function convertCharsetFromDatabase($text)
  370. {
  371. //Logger::debug('from '.$text);
  372. $dbCharset = @$this->conf['charset'];
  373. if ( !empty($dbCharset) && $dbCharset != 'UTF-8' )
  374. {
  375. //Logger::debug('Converting to UTF-8 from '.$dbCharset);
  376. if ( !function_exists('iconv') )
  377. Logger::warn('iconv not available - database charset unchanged. Please '.
  378. 'enable iconv on your system or transform your database content to UTF-8.');
  379. else
  380. $text = iconv($dbCharset,'UTF-8//TRANSLIT',$text);
  381. }
  382. //Logger::debug('to '.$text);
  383. return $text;
  384. }
  385. private function convertRowWithCharsetFromDatabase($row)
  386. {
  387. foreach( $row as $key=>$value)
  388. {
  389. $row[$key] = $this->convertCharsetFromDatabase($row[$key]);
  390. }
  391. return $row;
  392. }
  393. }
  394. ?>