com.lokorin.lokorin.lib
[ class tree: com.lokorin.lokorin.lib ] [ index: com.lokorin.lokorin.lib ] [ all elements ]

Source for file lib_db.php

Documentation is available at lib_db.php

  1. <?php
  2. /*
  3. * Lokorin.com
  4. * Copyright 2004-2006
  5. * Licensed under the GNU LGPL. See COPYING for full terms.
  6. */
  7. /**
  8. * A library designed to abstract the database interaction. The library
  9. * provides functions to the most common operations, cutting down on the
  10. * repetitiveness of building queries. It also improves readability and avoids
  11. * unnecessary code.
  12. * @author Andreas Launila
  13. * @version $Revision: 1.16 $
  14. * @package com.lokorin.lokorin.lib
  15. * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
  16. */
  17.  
  18. $tablePrefix = 'lok_';
  19. /**#@+
  20. * Site specific table name constants.
  21. * @access public
  22. * @var string
  23. */
  24. define('TABLE_NEWS', $tablePrefix.'news');
  25. define('TABLE_MENU', $tablePrefix.'menu');
  26. define('TABLE_ERRORS', $tablePrefix.'errors');
  27. define('TABLE_PROJECTS', $tablePrefix.'projects');
  28. define('TABLE_ADMIN_LOGS', $tablePrefix.'admin_logs');
  29. define('TABLE_PROGRAM_LANGS', $tablePrefix.'program_languages');
  30. define('TABLE_DOWNLOADS', $tablePrefix.'downloads');
  31. define('TABLE_COUNTERS', $tablePrefix.'counters');
  32. define('TABLE_EVENTS', $tablePrefix.'events');
  33. define('TABLE_DKPBANK', $tablePrefix.'dkpbank');
  34. define('TABLE_DKPBANK_MEMBERS', $tablePrefix.'dkpbank_members');
  35. define('TABLE_DKPBANK_IMAGES', $tablePrefix.'dkpbank_images');
  36. define('TABLE_LINK_CATEGORIES', $tablePrefix.'link_categories');
  37. define('TABLE_LINKS', $tablePrefix.'links');
  38. define('TABLE_COMMENTS', $tablePrefix.'comments');
  39. define('TABLE_PROJECT_IMAGES', $tablePrefix.'project_images');
  40. define('TABLE_PROJECT_SUBMENUS', $tablePrefix.'project_submenus');
  41. define('TABLE_PROJECT_STAGES', $tablePrefix.'project_stages');
  42. define('TABLE_MAPPED_URLS', $tablePrefix.'mapped_urls');
  43. define('TABLE_CUSTOM_ALIASES', $tablePrefix.'custom_aliases');
  44. define('TABLE_ALIASES', $tablePrefix.'aliases');
  45. define('TABLE_CUSTOM_REDIRECTS', $tablePrefix.'custom_redirects');
  46. define('TABLE_REDIRECTS', $tablePrefix.'redirects');
  47. define('TABLE_ABBR', $tablePrefix.'abbreviations');
  48. define('TABLE_PERFORMANCE', $tablePrefix.'performance');
  49. define('TABLE_SITEMAP', $tablePrefix.'sitemap');
  50. define('TABLE_DOWNLOAD_CATEGORIES', $tablePrefix.'download_categories');
  51. /**#@-*/ = 'mplf_';
  52. /**#@+
  53. * Table name constants for the MPLF archive.
  54. * @access public
  55. * @var string
  56. */
  57. define('TABLE_MPLF_FILTERS', $mplfPrefix.'filters');
  58. define('TABLE_MPLF_CATEGORIES', $mplfPrefix.'categories');
  59. define('TABLE_MPLF_EDITS', $mplfPrefix.'edits');
  60. define('TABLE_MPLF_MODERATORS', $mplfPrefix.'moderators');
  61. define('TABLE_MPLF_CHANGES', $mplfPrefix.'changes');
  62. /**#@-*/ * Describes a database abstraction. The abstraction maintains a connection
  63. * which is instance specific. Hence it is recommended that only one global
  64. * instance is used.
  65. * @author Andreas Launila
  66. * @package com.lokorin.lokorin.lib
  67. */
  68. class DataBase {
  69. /**
  70. * The database connection to use.
  71. * @var mysqlconnection
  72. */
  73. private $connection;
  74. /**
  75. * Contains any queued queries.
  76. * @var array
  77. */
  78. private $queue = array();
  79. /**
  80. * The number of queries that have been performed by the database. 0 means
  81. * that no queries have been performed.
  82. * @var integer
  83. */
  84. private $queryCount;
  85. /**
  86. * The number of milliseconds that have elapsed while waiting for the
  87. * database to complete a query. This is the sum of all query times.
  88. * @var integer
  89. */
  90. private $queryDuration;
  91. /**
  92. * The one and only instance of the class.
  93. * @var DB
  94. */
  95. private static $instance;
  96.  
  97. /**
  98. * Gets the one and only instance of the class.
  99. * @return DB The one and only instance.
  100. */
  101. public static function getInstance() {
  102. if(!isset(DataBase::$instance)) {
  103. DataBase::$instance = new DataBase();
  104. }
  105. return DataBase::$instance;
  106. }
  107.  
  108. /**
  109. * Constructor for DB.
  110. */
  111. private function __construct() {
  112. $this->queryCount = 0;
  113. $this->queryDuration = 0;
  114. }
  115.  
  116. /**
  117. * Connects to mysql and selects the correct databse.
  118. */
  119. private function connectToDb() {
  120. $this->connection = mysql_connect('localhost', 'root', 'starstorm');
  121. if(!$this->connection) {
  122. logFatalException(new Exception('Connection failed: '.mysql_error()));
  123. }
  124. mysql_select_db('lokorin_com',$this->connection) or die("Failed to select the database.");
  125. }
  126.  
  127. /**
  128. * Ensures that there is a active valid connection the the database. Id
  129. * there is an active and valid connection then nothing is done, otherwise
  130. * a connection is created.
  131. */
  132. private function ensureConnected() {
  133. if(!isset($this->connection)) {
  134. $this->connectToDB();
  135. }
  136. }
  137.  
  138. /**
  139. * Performs a specified query on the database.
  140. * @param string $query The query that should be performed.
  141. * @return mysqlresult The result resource of the query.
  142. */
  143. public function query($query) {
  144. $this->ensureConnected();
  145. //Start the query timing.
  146. $start = microtime(true);
  147. $result = mysql_query($query, $this->connection);
  148. if(!$result) {
  149. logFatalException(new Exception('Invalid MySQL query: '.
  150. mysql_error()."\n Query: ".$query));
  151. }
  152. //Log the result of the timing.
  153. $elapsedTime = round((microtime(true) - $start)*pow(10, 6));
  154. $this->queryDuration += $elapsedTime;
  155. $this->queryCount++;
  156. return $result;
  157. }
  158. /**
  159. * Escapes any special characters in the specified value. The result is
  160. * also quoted if it is not numeric. All field values should be run
  161. * through this function to ensure security.
  162. * @param mixed $value The value that should be escaped.
  163. * @return mixed The escaped version of the value, with appropriate quotes
  164. * if it is not numeric.
  165. */
  166. public function escape($value) {
  167. $this->ensureConnected();
  168. //Stripslashes
  169. if(get_magic_quotes_gpc()) {
  170. $value = stripslashes($value);
  171. }
  172. if(!is_int($value) && $value == '') {
  173. //Handle empty non integer values.
  174. return "''";
  175. } if(ctype_digit((string)$value)) {
  176. //Do nothing if digits.
  177. return $value;
  178. } else {
  179. //Quote if not digits.
  180. return "'".mysql_real_escape_string($value)."'";
  181. }
  182. }
  183.  
  184. /**
  185. * Builds and executes an insert query based on the specified table and
  186. * values.
  187. * @param string $tableName The name of the table that the query should
  188. * be executed on.
  189. * @param array $insertFields An array containing the values that should
  190. * be used to build the insert query. The key should be the field
  191. * name and the value should be the connected value for that field.
  192. * @return boolean True if the query was executed successfully, false
  193. * otherwise.
  194. */
  195. public function queryInsert($tableName, $insertFields = array()) {
  196. return $this->query($this->buildInsertQuery($tableName, $insertFields));
  197. }
  198.  
  199. /**
  200. * Builds an insert query based on the specified table and values.
  201. * @param string $tableName The name of the table that the values should
  202. * be inserted in.
  203. * @param array $insertFields An array containing the values that should
  204. * be used to build the insert query. The key should be the field
  205. * name and the value should be the connected value for that field.
  206. * @return string The resulting query.
  207. */
  208. public function buildInsertQuery($tableName, $insertFields = array()) {
  209. $query = "INSERT INTO `".$tableName."` (";
  210. $fields = '';
  211. $values = '';
  212. foreach($insertFields as $key => $value) {
  213. if($fields != '') {
  214. $fields .= ', ';
  215. }
  216. $fields .= '`'.$key.'`';
  217. if($values != '') {
  218. $values .= ', ';
  219. }
  220. $values .= $this->escape($value);
  221. }
  222. $query .= $fields.") VALUES (".$values.")";
  223. return $query;
  224. }
  225.  
  226. /**
  227. * Builds and executes a delete query on the specified table using the
  228. * specified values.
  229. * @param string $tableName The name of the table to delete rows from.
  230. * @param string $sqlSelector An sql selector to tell the query what rows
  231. * should be affected by the query.
  232. * @return boolean True if the query was executed successfully, false
  233. * otherwise.
  234. */
  235. public function queryDelete($tableName, $sqlSelector = '') {
  236. if(strlen($sqlSelector) == 0) {
  237. //Because of the possible consequences of letting this through as
  238. //a default it will be logged as a fatal exception instead.
  239. logFatalException(new IllegalArgumentException("Empty sqlSelectors" .
  240. "are not allowed, use TRUNCATE instead."));
  241. }
  242. return $this->query($this->buildDeleteQuery($tableName, $sqlSelector));
  243. }
  244. /**
  245. * Builds and executes a delete query for the specified table using the
  246. * specified values.
  247. * @param string $tableName The name of the table to delete rows from.
  248. * @param string $sqlSelector An sql selector to tell the query what rows
  249. * should be affected by the query.
  250. * @return string The resulting query.
  251. */
  252. public function buildDeleteQuery($tableName, $sqlSelector) {
  253. return "DELETE FROM `".$tableName."` ".$sqlSelector;
  254. }
  255.  
  256. /**
  257. * Builds and executes an update query on the specified table using the
  258. * specified values and selector.
  259. * @param string $tableName The name of the table to update.
  260. * @param array $updateFields The fields that should be updated for all
  261. * affected rows. The key is the field's name and the value is the
  262. * new value that the field should have.
  263. * @param string $sqlSelector An optional selector to tell the query what
  264. * rows should be affected by the query. The default is that all rows
  265. * are affected.
  266. * @return boolean True if the query was executed successfully, false
  267. * otherwise.
  268. */
  269. public function queryUpdate($tableName, $updateFields = array(), $sqlSelector = '') {
  270. return($this->query(
  271. $this->buildUpdateQuery($tableName, $updateFields, $sqlSelector)));
  272. }
  273. /**
  274. * Builds an update query for the specified table using the specified
  275. * values.
  276. * @param string $tableName The name of the table to update.
  277. * @param array $updateFields The fields that should be updated for all
  278. * affected rows. The key is the field's name and the value is the
  279. * new value that the field should have.
  280. * @param string $sqlSelector An optional selector to specify the resulting
  281. * selector even more. The parameter is appended onto the end of the
  282. * constructed selector.
  283. * @return string The resulting query.
  284. */
  285. public function buildUpdateQuery($tableName, $updateFields = array(), $sqlSelector = '') {
  286. $query = "UPDATE `".$tableName."` SET ";
  287. $variables = '';
  288. foreach($updateFields as $k => $value) {
  289. if($variables != '') {
  290. $variables .= ', ';
  291. }
  292. $variables .= '`'.$k."`=".$this->escape($value);
  293. }
  294. $query .= $variables." ".$sqlSelector;
  295. return $query;
  296. }
  297.  
  298. /**
  299. * Selects specific table fields from a specific table. The select
  300. * operation can also specify an optional sql selector.
  301. * @param string $tableName The name of the table to select from.
  302. * @param array $fields An array with the names of the fields that should
  303. * be selected.
  304. * @param string $sqlSelector Optional sql selector for the query.
  305. * @return array The selected rows and fields. The array contains one
  306. * array per row. Each of those array rows contain keys with
  307. * the specified field names along with the connected values.
  308. * If no values were found then an empty array will be returned.
  309. */
  310. public function querySelect($tableName, $fields, $sqlSelector = '') {
  311. if(!is_array($fields)) {
  312. return false;
  313. }
  314.  
  315. //Build the query.
  316. $query = "SELECT ";
  317. foreach($fields as $field) {
  318. if(strlen($query) > 7) {
  319. $query .= ", ";
  320. }
  321. $query .= '`'.$field.'`';
  322. }
  323. $query .= " FROM `".$tableName.'`';
  324. if($sqlSelector != '') {
  325. $query .= " ".$sqlSelector;
  326. }
  327.  
  328. //Run the query
  329. $result = $this->query($query);
  330. $rows = array();
  331. while($row = mysql_fetch_array($result)) {
  332. $currentRow = array();
  333. //Extract all the row values.
  334. foreach($fields as $field) {
  335. $currentRow[$field] = $row[$field];
  336. }
  337. $rows[] = $currentRow;
  338. }
  339. return $rows;
  340. }
  341. /**
  342. * Selects all table fields from a specific table. The select
  343. * operation can also specify an optional sql selector.
  344. * @param string $tableName The name of the table to select from.
  345. * @param string $sqlSelector Optional sql selector for the query.
  346. * @return array The selected rows and fields. The array contains one
  347. * array per row. Each of those array rows contain keys with
  348. * the field names along with the connected values. If no values
  349. * were found then an empty array will be returned.
  350. */
  351. public function querySelectAll($tableName, $sqlSelector = '') {
  352. //Build the query.
  353. $query = "SELECT * FROM `".$tableName.'`';
  354. if($sqlSelector != '') {
  355. $query .= " ".$sqlSelector;
  356. }
  357. //Run the query
  358. $result = $this->query($query);
  359. $rows = array();
  360. while($row = mysql_fetch_array($result)) {
  361. $rows[] = $row;
  362. }
  363. return $rows;
  364. }
  365. /**
  366. * Selects the first value found in a specified field in a specified table
  367. * that satisfies an sql selector.
  368. * @param string $tableName The name of the table to select from.
  369. * @param string $field The name of the table field from which the value
  370. * should be selected.
  371. * @param string $sqlSelector An sql selector for the query. The selector
  372. * specifies which rows that should be selected and which should be
  373. * ignored.
  374. * @return mixed The first value found that specifies all paramaters.
  375. * @throws NoSuchElementException If nor row matches the sql selector.
  376. */
  377. public function querySelectFirst($tableName, $field, $sqlSelector) {
  378. $rows = $this->querySelect($tableName, array($field), $sqlSelector);
  379. if(sizeof($rows) == 0) {
  380. throw new NoSuchElementException("Nothing matched the selector (" .
  381. $sqlSelector . ") in the table (" . $tableName . ")");
  382. }
  383. return $rows[0][$field];
  384. }
  385. /**
  386. * Gets the number of rows that matches specified conditions.
  387. * @param string $tableName The table name to count from.
  388. * @param string $sqlSelector An optional sql selector for the query. This
  389. * can be used to count a subset of the rows. The default is that all
  390. * rows are counted.
  391. * @return integer The number of rows that satisfy the specified
  392. * conditions.
  393. */
  394. public function queryCount($tableName, $sqlSelector = '') {
  395. $result = $this->query("SELECT COUNT(*) FROM `".$tableName."` ".$sqlSelector);
  396. list($count) = mysql_fetch_row($result);
  397. return $count;
  398. }
  399. /**
  400. * Builds a sql selector from specified field values.
  401. * @param array $fieldValues An array containing the specified values. The
  402. * key is the field name, the value is the value that the field should
  403. * have.
  404. * @return string A sqlSelector that specifies rows whos field have the
  405. * specified values. Returns a boolean false if the argument is not
  406. * an array.
  407. */
  408. public function buildSqlSelector($fieldValues) {
  409. if(!is_array($fieldValues)) {
  410. return false;
  411. }
  412. if(sizeof($fieldValues) == 0) {
  413. return '';
  414. }
  415. $sqlSelector = '';
  416. foreach($fieldValues as $key => $value) {
  417. if(strlen($sqlSelector) != 0) {
  418. $sqlSelector .= ' AND ';
  419. }
  420. $sqlSelector .= "(`".$key."`=".$this->escape($value).")";
  421. }
  422. return "WHERE ".$sqlSelector;
  423. }
  424.  
  425. /**
  426. * Gets the last generated identifier on a per-connection basis.
  427. * @return integer The last generated identifier.
  428. */
  429. public function getLastInsertId() {
  430. $this->ensureConnected();
  431. return mysql_insert_id();
  432. }
  433.  
  434. /**
  435. * Puts a specified query at the end of the queue.
  436. * @param string $query The query that should be added to the queue.
  437. */
  438. public function queueQuery($query) {
  439. $this->queue[] = $query;
  440. }
  441. /**
  442. * Flushes the queue, executing all queries in it in the order that they
  443. * were inserted and then clearing it.
  444. */
  445. public function flushQueue() {
  446. foreach($this->queue as $query) {
  447. $this->query($query);
  448. }
  449. $this->clearQueue;
  450. }
  451.  
  452. /**
  453. * Gets the number of queries in the queue.
  454. * @return integer A positive number.
  455. */
  456. public function getQueueSize() {
  457. return count($this->queue);
  458. }
  459.  
  460. /**
  461. * Clears the queue, removing all currently queued queries wihtout
  462. * executing them.
  463. */
  464. public function clearQueue() {
  465. $this->queue = array();
  466. }
  467. /**
  468. * Gets the number of queries that have been performed by the database
  469. * during the page request.
  470. * @return integer A non-negative number, 0 means that no queries have been
  471. * performed.
  472. */
  473. public function getQueryCount() {
  474. return $this->queryCount;
  475. }
  476. /**
  477. * Gets the number of milliseconds that the database has spent processing
  478. * queries during the page request.
  479. * @return integer A non-negative number, e.g. 10 means that 10
  480. * milliseconds have been spent on processing queries.
  481. */
  482. public function getElapsedQueryTime() {
  483. return $this->queryDuration;
  484. }
  485. }
  486.  
  487. ?>

Documentation generated on Sun, 16 Apr 2006 21:03:16 +0200 by phpDocumentor 1.3.0RC4