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

/textpattern/lib/txplib_db.php

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