PageRenderTime 59ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/textpattern/lib/txplib_db.php

https://github.com/nope/Tipattern
PHP | 501 lines | 389 code | 68 blank | 44 comment | 54 complexity | 9a486def3df433efb04f5bd85bf12a79 MD5 | raw file
  1. <?php
  2. /*
  3. $HeadURL$
  4. $LastChangedRevision$
  5. */
  6. if (!defined('PFX')) {
  7. if (!empty($txpcfg['table_prefix'])) {
  8. define ("PFX",$txpcfg['table_prefix']);
  9. } else define ("PFX",'');
  10. }
  11. if (get_magic_quotes_runtime())
  12. {
  13. set_magic_quotes_runtime(0);
  14. }
  15. class DB {
  16. function DB()
  17. {
  18. global $txpcfg;
  19. $this->host = $txpcfg['host'];
  20. $this->db = $txpcfg['db'];
  21. $this->user = $txpcfg['user'];
  22. $this->pass = $txpcfg['pass'];
  23. $this->client_flags = isset($txpcfg['client_flags']) ? $txpcfg['client_flags'] : 0;
  24. $this->link = @mysql_connect($this->host, $this->user, $this->pass, false, $this->client_flags);
  25. if (!$this->link) die(db_down());
  26. $this->version = mysql_get_server_info();
  27. if (!$this->link) {
  28. $GLOBALS['connected'] = false;
  29. } else $GLOBALS['connected'] = true;
  30. @mysql_select_db($this->db) or die(db_down());
  31. $version = $this->version;
  32. // be backwardscompatible
  33. if ( isset($txpcfg['dbcharset']) && (intval($version[0]) >= 5 || preg_match('#^4\.[1-9]#',$version)) )
  34. mysql_query("SET NAMES ". $txpcfg['dbcharset']);
  35. }
  36. }
  37. $DB = new DB;
  38. //-------------------------------------------------------------
  39. function safe_pfx($table) {
  40. $name = PFX.$table;
  41. if (preg_match('@[^\w._$]@', $name))
  42. return '`'.$name.'`';
  43. return $name;
  44. }
  45. //-------------------------------------------------------------
  46. function safe_pfx_j($table)
  47. {
  48. $ts = array();
  49. foreach (explode(',', $table) as $t) {
  50. $name = PFX.trim($t);
  51. if (preg_match('@[^\w._$]@', $name))
  52. $ts[] = "`$name`".(PFX ? " as `$t`" : '');
  53. else
  54. $ts[] = "$name".(PFX ? " as $t" : '');
  55. }
  56. return join(', ', $ts);
  57. }
  58. //-------------------------------------------------------------
  59. function safe_query($q='',$debug='',$unbuf='')
  60. {
  61. global $DB, $txpcfg, $qcount, $qtime, $production_status;
  62. $method = (!$unbuf) ? 'mysql_query' : 'mysql_unbuffered_query';
  63. if (!$q) return false;
  64. if ($debug or TXP_DEBUG === 1) dmp($q);
  65. $start = getmicrotime();
  66. $result = $method($q,$DB->link);
  67. $time = getmicrotime() - $start;
  68. @$qtime += $time;
  69. @$qcount++;
  70. if ($result === false and (txpinterface === 'admin' or @$production_status == 'debug' or @$production_status == 'testing')) {
  71. $caller = ($production_status == 'debug') ? n . join("\n", get_caller()) : '';
  72. trigger_error(mysql_error() . n . $q . $caller, E_USER_WARNING);
  73. }
  74. trace_add("[SQL ($time): $q]");
  75. if(!$result) return false;
  76. return $result;
  77. }
  78. // -------------------------------------------------------------
  79. function safe_delete($table, $where, $debug='')
  80. {
  81. $q = "delete from ".safe_pfx($table)." where $where";
  82. if ($r = safe_query($q,$debug)) {
  83. return true;
  84. }
  85. return false;
  86. }
  87. // -------------------------------------------------------------
  88. function safe_update($table, $set, $where, $debug='')
  89. {
  90. $q = "update ".safe_pfx($table)." set $set where $where";
  91. if ($r = safe_query($q,$debug)) {
  92. return true;
  93. }
  94. return false;
  95. }
  96. // -------------------------------------------------------------
  97. function safe_insert($table,$set,$debug='')
  98. {
  99. global $DB;
  100. $q = "insert into ".safe_pfx($table)." set $set";
  101. if ($r = safe_query($q,$debug)) {
  102. $id = mysql_insert_id($DB->link);
  103. return ($id === 0 ? true : $id);
  104. }
  105. return false;
  106. }
  107. // -------------------------------------------------------------
  108. // insert or update
  109. function safe_upsert($table,$set,$where,$debug='')
  110. {
  111. // FIXME: lock the table so this is atomic?
  112. $r = safe_update($table, $set, $where, $debug);
  113. if ($r and (mysql_affected_rows() or safe_count($table, $where, $debug)))
  114. return $r;
  115. else
  116. return safe_insert($table, join(', ', array($where, $set)), $debug);
  117. }
  118. // -------------------------------------------------------------
  119. function safe_alter($table, $alter, $debug='')
  120. {
  121. $q = "alter table ".safe_pfx($table)." $alter";
  122. if ($r = safe_query($q,$debug)) {
  123. return true;
  124. }
  125. return false;
  126. }
  127. // -------------------------------------------------------------
  128. function safe_optimize($table, $debug='')
  129. {
  130. $q = "optimize table ".safe_pfx($table)."";
  131. if ($r = safe_query($q,$debug)) {
  132. return true;
  133. }
  134. return false;
  135. }
  136. // -------------------------------------------------------------
  137. function safe_repair($table, $debug='')
  138. {
  139. $q = "repair table ".safe_pfx($table)."";
  140. if ($r = safe_query($q,$debug)) {
  141. return true;
  142. }
  143. return false;
  144. }
  145. // -------------------------------------------------------------
  146. function safe_field($thing, $table, $where, $debug='')
  147. {
  148. $q = "select $thing from ".safe_pfx_j($table)." where $where";
  149. $r = safe_query($q,$debug);
  150. if (@mysql_num_rows($r) > 0) {
  151. $f = mysql_result($r,0);
  152. mysql_free_result($r);
  153. return $f;
  154. }
  155. return false;
  156. }
  157. // -------------------------------------------------------------
  158. function safe_column($thing, $table, $where, $debug='')
  159. {
  160. $q = "select $thing from ".safe_pfx_j($table)." where $where";
  161. $rs = getRows($q,$debug);
  162. if ($rs) {
  163. foreach($rs as $a) {
  164. $v = array_shift($a);
  165. $out[$v] = $v;
  166. }
  167. return $out;
  168. }
  169. return array();
  170. }
  171. // -------------------------------------------------------------
  172. function safe_row($things, $table, $where, $debug='')
  173. {
  174. $q = "select $things from ".safe_pfx_j($table)." where $where";
  175. $rs = getRow($q,$debug);
  176. if ($rs) {
  177. return $rs;
  178. }
  179. return array();
  180. }
  181. // -------------------------------------------------------------
  182. function safe_rows($things, $table, $where, $debug='')
  183. {
  184. $q = "select $things from ".safe_pfx_j($table)." where $where";
  185. $rs = getRows($q,$debug);
  186. if ($rs) {
  187. return $rs;
  188. }
  189. return array();
  190. }
  191. // -------------------------------------------------------------
  192. function safe_rows_start($things, $table, $where, $debug='')
  193. {
  194. $q = "select $things from ".safe_pfx_j($table)." where $where";
  195. return startRows($q,$debug);
  196. }
  197. //-------------------------------------------------------------
  198. function safe_count($table, $where, $debug='')
  199. {
  200. return getThing("select count(*) from ".safe_pfx_j($table)." where $where",$debug);
  201. }
  202. // -------------------------------------------------------------
  203. function safe_show($thing, $table, $debug='')
  204. {
  205. $q = "show $thing from ".safe_pfx($table)."";
  206. $rs = getRows($q,$debug);
  207. if ($rs) {
  208. return $rs;
  209. }
  210. return array();
  211. }
  212. //-------------------------------------------------------------
  213. function fetch($col,$table,$key,$val,$debug='')
  214. {
  215. $key = doSlash($key);
  216. $val = (is_int($val)) ? $val : "'".doSlash($val)."'";
  217. $q = "select $col from ".safe_pfx($table)." where `$key` = $val limit 1";
  218. if ($r = safe_query($q,$debug)) {
  219. $thing = (mysql_num_rows($r) > 0) ? mysql_result($r,0) : '';
  220. mysql_free_result($r);
  221. return $thing;
  222. }
  223. return false;
  224. }
  225. //-------------------------------------------------------------
  226. function getRow($query,$debug='')
  227. {
  228. if ($r = safe_query($query,$debug)) {
  229. $row = (mysql_num_rows($r) > 0) ? mysql_fetch_assoc($r) : false;
  230. mysql_free_result($r);
  231. return $row;
  232. }
  233. return false;
  234. }
  235. //-------------------------------------------------------------
  236. function getRows($query,$debug='')
  237. {
  238. if ($r = safe_query($query,$debug)) {
  239. if (mysql_num_rows($r) > 0) {
  240. while ($a = mysql_fetch_assoc($r)) $out[] = $a;
  241. mysql_free_result($r);
  242. return $out;
  243. }
  244. }
  245. return false;
  246. }
  247. //-------------------------------------------------------------
  248. function startRows($query,$debug='')
  249. {
  250. return safe_query($query,$debug);
  251. }
  252. //-------------------------------------------------------------
  253. function nextRow($r)
  254. {
  255. $row = mysql_fetch_assoc($r);
  256. if ($row === false)
  257. mysql_free_result($r);
  258. return $row;
  259. }
  260. //-------------------------------------------------------------
  261. function numRows($r)
  262. {
  263. return mysql_num_rows($r);
  264. }
  265. //-------------------------------------------------------------
  266. function getThing($query,$debug='')
  267. {
  268. if ($r = safe_query($query,$debug)) {
  269. $thing = (mysql_num_rows($r) != 0) ? mysql_result($r,0) : '';
  270. mysql_free_result($r);
  271. return $thing;
  272. }
  273. return false;
  274. }
  275. //-------------------------------------------------------------
  276. function getThings($query,$debug='')
  277. // return values of one column from multiple rows in an num indexed array
  278. {
  279. $rs = getRows($query,$debug);
  280. if ($rs) {
  281. foreach($rs as $a) $out[] = array_shift($a);
  282. return $out;
  283. }
  284. return array();
  285. }
  286. //-------------------------------------------------------------
  287. function getCount($table,$where,$debug='')
  288. {
  289. return getThing("select count(*) from ".safe_pfx_j($table)." where $where",$debug);
  290. }
  291. // -------------------------------------------------------------
  292. function getTree($root, $type, $where='1=1', $tbl='txp_category')
  293. {
  294. $root = doSlash($root);
  295. $type = doSlash($type);
  296. $rs = safe_row(
  297. "lft as l, rgt as r",
  298. $tbl,
  299. "name='$root' and type = '$type'"
  300. );
  301. if (!$rs) return array();
  302. extract($rs);
  303. $out = array();
  304. $right = array();
  305. $rs = safe_rows_start(
  306. "id, name, lft, rgt, parent, title",
  307. $tbl,
  308. "lft between $l and $r and type = '$type' and name != 'root' and $where order by lft asc"
  309. );
  310. while ($rs and $row = nextRow($rs)) {
  311. extract($row);
  312. while (count($right) > 0 && $right[count($right)-1] < $rgt) {
  313. array_pop($right);
  314. }
  315. $out[] =
  316. array(
  317. 'id' => $id,
  318. 'name' => $name,
  319. 'title' => $title,
  320. 'level' => count($right),
  321. 'children' => ($rgt - $lft - 1) / 2,
  322. 'parent' => $parent
  323. );
  324. $right[] = $rgt;
  325. }
  326. return($out);
  327. }
  328. // -------------------------------------------------------------
  329. function getTreePath($target, $type, $tbl='txp_category')
  330. {
  331. $rs = safe_row(
  332. "lft as l, rgt as r",
  333. $tbl,
  334. "name='".doSlash($target)."' and type = '".doSlash($type)."'"
  335. );
  336. if (!$rs) return array();
  337. extract($rs);
  338. $rs = safe_rows_start(
  339. "*",
  340. $tbl,
  341. "lft <= $l and rgt >= $r and type = '".doSlash($type)."' order by lft asc"
  342. );
  343. $out = array();
  344. $right = array();
  345. while ($rs and $row = nextRow($rs)) {
  346. extract($row);
  347. while (count($right) > 0 && $right[count($right)-1] < $rgt) {
  348. array_pop($right);
  349. }
  350. $out[] =
  351. array(
  352. 'id' => $id,
  353. 'name' => $name,
  354. 'title' => $title,
  355. 'level' => count($right),
  356. 'children' => ($rgt - $lft - 1) / 2
  357. );
  358. $right[] = $rgt;
  359. }
  360. return $out;
  361. }
  362. // -------------------------------------------------------------
  363. function rebuild_tree($parent, $left, $type, $tbl='txp_category')
  364. {
  365. $left = assert_int($left);
  366. $right = $left+1;
  367. $parent = doSlash($parent);
  368. $type = doSlash($type);
  369. $result = safe_column("name", $tbl,
  370. "parent='$parent' and type='$type' order by name");
  371. foreach($result as $row) {
  372. $right = rebuild_tree($row, $right, $type, $tbl);
  373. }
  374. safe_update(
  375. $tbl,
  376. "lft=$left, rgt=$right",
  377. "name='$parent' and type='$type'"
  378. );
  379. return $right+1;
  380. }
  381. //-------------------------------------------------------------
  382. function rebuild_tree_full($type, $tbl='txp_category')
  383. {
  384. # fix circular references, otherwise rebuild_tree() could get stuck in a loop
  385. safe_update($tbl, "parent=''", "type='".doSlash($type)."' and name='root'");
  386. safe_update($tbl, "parent='root'", "type='".doSlash($type)."' and parent=name");
  387. rebuild_tree('root', 1, $type, $tbl);
  388. }
  389. //-------------------------------------------------------------
  390. function get_prefs()
  391. {
  392. global $txp_user;
  393. $out = array();
  394. // get current user's private prefs
  395. if ($txp_user) {
  396. $r = safe_rows_start('name, val', 'txp_prefs', 'prefs_id=1 AND user_name=\''.doSlash($txp_user).'\'');
  397. if ($r) {
  398. while ($a = nextRow($r)) {
  399. $out[$a['name']] = $a['val'];
  400. }
  401. }
  402. }
  403. // get global prefs, eventually override equally named user prefs.
  404. $r = safe_rows_start('name, val', 'txp_prefs', 'prefs_id=1 AND user_name=\'\'');
  405. if ($r) {
  406. while ($a = nextRow($r)) {
  407. $out[$a['name']] = $a['val'];
  408. }
  409. }
  410. return $out;
  411. }
  412. // -------------------------------------------------------------
  413. function db_down()
  414. {
  415. // 503 status might discourage search engines from indexing or caching the error message
  416. txp_status_header('503 Service Unavailable');
  417. $error = mysql_error();
  418. return <<<eod
  419. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  420. "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  421. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  422. <head>
  423. <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  424. <title>Untitled</title>
  425. </head>
  426. <body>
  427. <p align="center" style="margin-top:4em">Database unavailable.</p>
  428. <!-- $error -->
  429. </body>
  430. </html>
  431. eod;
  432. }
  433. ?>