PageRenderTime 48ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/blog/wp-content/plugins/w3-total-cache/lib/W3/Db.php

https://github.com/kennethreitz-archive/wordpress-skeleton
PHP | 577 lines | 320 code | 85 blank | 172 comment | 51 complexity | 674d69aea9e36d97091124d4d5ffd13d MD5 | raw file
  1. <?php
  2. /**
  3. * W3 Database object
  4. */
  5. $wpdb = false;
  6. require_once ABSPATH . 'wp-includes/wp-db.php';
  7. /**
  8. * Class W3_Db
  9. */
  10. class W3_Db extends wpdb
  11. {
  12. /**
  13. * Array of queries
  14. *
  15. * @var array
  16. */
  17. var $query_stats = array();
  18. /**
  19. * Queries total
  20. *
  21. * @var integer
  22. */
  23. var $query_total = 0;
  24. /**
  25. * Query cache hits
  26. *
  27. * @var integer
  28. */
  29. var $query_hits = 0;
  30. /**
  31. * Query cache misses
  32. *
  33. * @var integer
  34. */
  35. var $query_misses = 0;
  36. /**
  37. * Time total
  38. *
  39. * @var integer
  40. */
  41. var $time_total = 0;
  42. /**
  43. * Config
  44. *
  45. * @var W3_Config
  46. */
  47. var $_config = null;
  48. /**
  49. * Lifetime
  50. *
  51. * @var integer
  52. */
  53. var $_lifetime = null;
  54. /**
  55. * PHP5 constructor
  56. *
  57. * @param string $dbuser
  58. * @param string $dbpassword
  59. * @param string $dbname
  60. * @param string $dbhost
  61. */
  62. function __construct($dbuser, $dbpassword, $dbname, $dbhost)
  63. {
  64. require_once W3TC_LIB_W3_DIR . '/Config.php';
  65. $this->_config = & W3_Config::instance();
  66. $this->_lifetime = $this->_config->get_integer('dbcache.lifetime');
  67. if ($this->_config->get_boolean('dbcache.enabled') && $this->_config->get_boolean('dbcache.debug')) {
  68. ob_start(array(
  69. &$this,
  70. 'ob_callback'
  71. ));
  72. }
  73. parent::__construct($dbuser, $dbpassword, $dbname, $dbhost);
  74. }
  75. /**
  76. * PHP4 constructor
  77. *
  78. * @param string $dbuser
  79. * @param string $dbpassword
  80. * @param string $dbname
  81. * @param string $dbhost
  82. */
  83. function W3_Db($dbuser, $dbpassword, $dbname, $dbhost)
  84. {
  85. $this->__construct($dbuser, $dbpassword, $dbname, $dbhost);
  86. }
  87. /**
  88. * Executes query
  89. *
  90. * @param string $query
  91. * @return integer
  92. */
  93. function query($query)
  94. {
  95. if (!$this->ready) {
  96. return false;
  97. }
  98. ++$this->query_total;
  99. // Filter the query, if filters are available
  100. // NOTE: Some queries are made before the plugins have been loaded, and thus cannot be filtered with this method
  101. if (function_exists('apply_filters')) {
  102. $query = apply_filters('query', $query);
  103. }
  104. // Initialise return
  105. $return_val = 0;
  106. $this->flush();
  107. // Log how the function was called
  108. $this->func_call = "\$db->query(\"$query\")";
  109. // Keep track of the last query for debug..
  110. $this->last_query = $query;
  111. $reason = '';
  112. $caching = $this->can_cache($query, $reason);
  113. $cached = false;
  114. $data = false;
  115. $time_total = 0;
  116. if ($caching) {
  117. $cache_key = $this->_get_cache_key($query);
  118. $this->timer_start();
  119. $cache = & $this->_get_cache();
  120. $data = $cache->get($cache_key);
  121. $time_total = $this->timer_stop();
  122. }
  123. /**
  124. * Check if query was cached
  125. */
  126. if (is_array($data)) {
  127. ++$this->query_hits;
  128. $cached = true;
  129. /**
  130. * Set result from the cache
  131. */
  132. $this->last_error = $data['last_error'];
  133. $this->last_query = $data['last_query'];
  134. $this->last_result = $data['last_result'];
  135. $this->col_info = $data['col_info'];
  136. $this->num_rows = $data['num_rows'];
  137. } else {
  138. ++$this->num_queries;
  139. ++$this->query_misses;
  140. // Perform the query via std mysql_query function..
  141. $this->timer_start();
  142. $this->result = @mysql_query($query, $this->dbh);
  143. $time_total = $this->timer_stop();
  144. if (defined('SAVEQUERIES') && SAVEQUERIES) {
  145. $this->queries[] = array(
  146. $query,
  147. $time_total,
  148. $this->get_caller()
  149. );
  150. }
  151. // If there is an error then take note of it..
  152. if (($this->last_error = mysql_error($this->dbh))) {
  153. $this->print_error();
  154. return false;
  155. }
  156. if (preg_match("/^\\s*(insert|delete|update|replace|alter)\\s+/si", $query)) {
  157. $this->rows_affected = mysql_affected_rows($this->dbh);
  158. // Take note of the insert_id
  159. if (preg_match("/^\\s*(insert|replace) /i", $query)) {
  160. $this->insert_id = mysql_insert_id($this->dbh);
  161. }
  162. // Return number of rows affected
  163. $return_val = $this->rows_affected;
  164. } elseif (is_resource($this->result)) {
  165. $i = 0;
  166. while ($i < @mysql_num_fields($this->result)) {
  167. $this->col_info[$i] = @mysql_fetch_field($this->result);
  168. $i++;
  169. }
  170. $num_rows = 0;
  171. while (($row = @mysql_fetch_object($this->result))) {
  172. $this->last_result[$num_rows] = $row;
  173. $num_rows++;
  174. }
  175. @mysql_free_result($this->result);
  176. // Log number of rows the query returned
  177. $this->num_rows = $num_rows;
  178. // Return number of rows selected
  179. $return_val = $this->num_rows;
  180. if ($caching) {
  181. /**
  182. * Store result to the cache
  183. */
  184. $data = array(
  185. 'last_error' => $this->last_error,
  186. 'last_query' => $this->last_query,
  187. 'last_result' => $this->last_result,
  188. 'col_info' => $this->col_info,
  189. 'num_rows' => $this->num_rows
  190. );
  191. $cache = & $this->_get_cache();
  192. $cache->set($cache_key, $data, $this->_lifetime);
  193. }
  194. }
  195. }
  196. if ($this->_config->get_boolean('dbcache.debug')) {
  197. $this->query_stats[] = array(
  198. 'query' => $query,
  199. 'caching' => $caching,
  200. 'reason' => $reason,
  201. 'cached' => $cached,
  202. 'time_total' => $time_total
  203. );
  204. }
  205. $this->time_total += $time_total;
  206. return $return_val;
  207. }
  208. /**
  209. * Check if can cache sql
  210. *
  211. * @param string $sql
  212. * @return boolean
  213. */
  214. function can_cache($sql, &$cache_reject_reason)
  215. {
  216. /**
  217. * Skip if disabled
  218. */
  219. if (!$this->_config->get_boolean('dbcache.enabled')) {
  220. $cache_reject_reason = 'database caching is disabled';
  221. return false;
  222. }
  223. /**
  224. * Skip if doint AJAX
  225. */
  226. if (defined('DOING_AJAX')) {
  227. $cache_reject_reason = 'doing AJAX';
  228. return false;
  229. }
  230. /**
  231. * Skip if doing cron
  232. */
  233. if (defined('DOING_CRON')) {
  234. $cache_reject_reason = 'doing cron';
  235. return false;
  236. }
  237. /**
  238. * Skip if APP request
  239. */
  240. if (defined('APP_REQUEST')) {
  241. $cache_reject_reason = 'application request';
  242. return false;
  243. }
  244. /**
  245. * Skip if XMLRPC request
  246. */
  247. if (defined('XMLRPC_REQUEST')) {
  248. $cache_reject_reason = 'XMLRPC request';
  249. return false;
  250. }
  251. /**
  252. * Skip if admin
  253. */
  254. if (defined('WP_ADMIN')) {
  255. $cache_reject_reason = 'wp-admin';
  256. return false;
  257. }
  258. /**
  259. * Skip if SQL is rejected
  260. */
  261. if (!$this->_check_sql($sql)) {
  262. $cache_reject_reason = 'query is rejected';
  263. return false;
  264. }
  265. /**
  266. * Skip if request URI is rejected
  267. */
  268. if (!$this->_check_request_uri()) {
  269. $cache_reject_reason = 'request URI is rejected';
  270. return false;
  271. }
  272. /**
  273. * Skip if cookie is rejected
  274. */
  275. if (!$this->_check_cookies()) {
  276. $cache_reject_reason = 'cookie is rejected';
  277. return false;
  278. }
  279. /**
  280. * Skip if user is logged in
  281. */
  282. if ($this->_config->get_boolean('dbcache.reject.logged') && !$this->_check_logged_in()) {
  283. $cache_reject_reason = 'user is logged in';
  284. return false;
  285. }
  286. return true;
  287. }
  288. /**
  289. * Flushes cache
  290. *
  291. * @return boolean
  292. */
  293. function flush_cache()
  294. {
  295. $cache = & $this->_get_cache();
  296. return $cache->flush();
  297. }
  298. /**
  299. * Returns onject instance
  300. *
  301. * @return W3_Db
  302. */
  303. function &instance()
  304. {
  305. static $instances = array();
  306. if (!isset($instances[0])) {
  307. $class = __CLASS__;
  308. $instances[0] = & new $class(DB_USER, DB_PASSWORD, DB_NAME, DB_HOST);
  309. }
  310. return $instances[0];
  311. }
  312. /**
  313. * Output buffering callback
  314. *
  315. * @param string $buffer
  316. * @return string
  317. */
  318. function ob_callback($buffer)
  319. {
  320. if ($buffer != '' && w3_is_xml($buffer)) {
  321. $buffer .= "\r\n\r\n" . $this->_get_debug_info();
  322. }
  323. return $buffer;
  324. }
  325. /**
  326. * Returns cache object
  327. *
  328. * @return W3_Cache_Base
  329. */
  330. function &_get_cache()
  331. {
  332. static $cache = array();
  333. if (!isset($cache[0])) {
  334. $engine = $this->_config->get_string('dbcache.engine');
  335. switch ($engine) {
  336. case 'memcached':
  337. $engineConfig = array(
  338. 'servers' => $this->_config->get_array('dbcache.memcached.servers'),
  339. 'persistant' => $this->_config->get_boolean('dbcache.memcached.persistant')
  340. );
  341. break;
  342. case 'file':
  343. $engineConfig = array(
  344. 'cache_dir' => W3TC_CACHE_FILE_DBCACHE_DIR
  345. );
  346. break;
  347. default:
  348. $engineConfig = array();
  349. }
  350. require_once W3TC_LIB_W3_DIR . '/Cache.php';
  351. $cache[0] = & W3_Cache::instance($engine, $engineConfig);
  352. }
  353. return $cache[0];
  354. }
  355. /**
  356. * Check SQL
  357. *
  358. * @param string $sql
  359. * @return boolean
  360. */
  361. function _check_sql($sql)
  362. {
  363. $auto_reject_strings = array(
  364. '^\s*insert\b',
  365. '^\s*delete\b',
  366. '^\s*update\b',
  367. '^\s*replace\b',
  368. '^\s*create\b',
  369. '^\s*alter\b',
  370. '^\s*show\b',
  371. '^\s*set\b',
  372. '\bsql_calc_found_rows\b',
  373. '\bfound_rows\(\)',
  374. '\bautoload\s+=\s+\'yes\'',
  375. '\bw3tc_request_data\b'
  376. );
  377. if (preg_match('@' . implode('|', $auto_reject_strings) . '@is', $sql)) {
  378. return false;
  379. }
  380. $reject_sql = $this->_config->get_array('dbcache.reject.sql');
  381. foreach ($reject_sql as $expr) {
  382. $expr = trim($expr);
  383. $expr = str_replace('{prefix}', $this->prefix, $expr);
  384. if ($expr != '' && preg_match('@' . $expr . '@i', $sql)) {
  385. return false;
  386. }
  387. }
  388. return true;
  389. }
  390. /**
  391. * Check request URI
  392. *
  393. * @return boolean
  394. */
  395. function _check_request_uri()
  396. {
  397. $auto_reject_uri = array(
  398. 'wp-login',
  399. 'wp-register'
  400. );
  401. foreach ($auto_reject_uri as $uri) {
  402. if (strstr($_SERVER['REQUEST_URI'], $uri) !== false) {
  403. return false;
  404. }
  405. }
  406. $reject_uri = $this->_config->get_array('dbcache.reject.uri');
  407. foreach ($reject_uri as $expr) {
  408. $expr = trim($expr);
  409. if ($expr != '' && preg_match('@' . $expr . '@i', $_SERVER['REQUEST_URI'])) {
  410. return false;
  411. }
  412. }
  413. return true;
  414. }
  415. /**
  416. * Checks for WordPress cookies
  417. *
  418. * @return boolean
  419. */
  420. function _check_cookies()
  421. {
  422. foreach (array_keys($_COOKIE) as $cookie_name) {
  423. if ($cookie_name == 'wordpress_test_cookie') {
  424. continue;
  425. }
  426. if (preg_match('/^wp-postpass|^comment_author/', $cookie_name)) {
  427. return false;
  428. }
  429. }
  430. foreach ($this->_config->get_array('dbcache.reject.cookie') as $reject_cookie) {
  431. foreach (array_keys($_COOKIE) as $cookie_name) {
  432. if (strstr($cookie_name, $reject_cookie) !== false) {
  433. return false;
  434. }
  435. }
  436. }
  437. return true;
  438. }
  439. /**
  440. * Check if user is logged in
  441. *
  442. * @return boolean
  443. */
  444. function _check_logged_in()
  445. {
  446. foreach (array_keys($_COOKIE) as $cookie_name) {
  447. if ($cookie_name == 'wordpress_test_cookie') {
  448. continue;
  449. }
  450. if (strpos($cookie_name, 'wordpress') === 0) {
  451. return false;
  452. }
  453. }
  454. return true;
  455. }
  456. /**
  457. * Returns cache key
  458. *
  459. * @param string $sql
  460. * @return string
  461. */
  462. function _get_cache_key($sql)
  463. {
  464. $blogname = w3_get_blogname();
  465. if ($blogname == '') {
  466. $blogname = $_SERVER['HTTP_HOST'];
  467. }
  468. return sprintf('w3tc_%s_sql_%s', md5($blogname), md5($sql));
  469. }
  470. /**
  471. * Returns debug info
  472. *
  473. * @return string
  474. */
  475. function _get_debug_info()
  476. {
  477. $debug_info = "<!-- W3 Total Cache: Db cache debug info:\r\n";
  478. $debug_info .= sprintf("%s%s\r\n", str_pad('Engine: ', 20), w3_get_engine_name($this->_config->get_string('dbcache.engine')));
  479. $debug_info .= sprintf("%s%d\r\n", str_pad('Total queries: ', 20), $this->query_total);
  480. $debug_info .= sprintf("%s%d\r\n", str_pad('Cached queries: ', 20), $this->query_hits);
  481. $debug_info .= sprintf("%s%.3f\r\n", str_pad('Total query time: ', 20), $this->time_total);
  482. if (count($this->query_stats)) {
  483. $debug_info .= "SQL info:\r\n";
  484. $debug_info .= sprintf("%s | %s | %s | % s | %s\r\n", str_pad('#', 5, ' ', STR_PAD_LEFT), str_pad('Time (s)', 8, ' ', STR_PAD_LEFT), str_pad('Caching (Reject reason)', 30, ' ', STR_PAD_BOTH), str_pad('Status', 10, ' ', STR_PAD_BOTH), 'Query');
  485. foreach ($this->query_stats as $index => $query) {
  486. $debug_info .= sprintf("%s | %s | %s | %s | %s\r\n", str_pad($index + 1, 5, ' ', STR_PAD_LEFT), str_pad(round($query['time_total'], 3), 8, ' ', STR_PAD_LEFT), str_pad(($query['caching'] ? 'enabled' : sprintf('disabled (%s)', $query['reason'])), 30, ' ', STR_PAD_BOTH), str_pad(($query['cached'] ? 'Cached' : 'Not cached'), 10, ' ', STR_PAD_BOTH), str_replace('-->', '-- >', trim($query['query'])));
  487. }
  488. }
  489. $debug_info .= '-->';
  490. return $debug_info;
  491. }
  492. }