_config = W3_Config::instance(); parent::__construct($dbuser, $dbpassword, $dbname, $dbhost); } /** * PHP4 constructor * * @param string $dbuser * @param string $dbpassword * @param string $dbname * @param string $dbhost */ function W3_Db($dbuser, $dbpassword, $dbname, $dbhost) { $this->__construct($dbuser, $dbpassword, $dbname, $dbhost); } /** * Executes query * * @param string $query * @return integer */ function query($query) { if (! $this->ready) { return false; } ++ $this->query_total; // filter the query, if filters are available // NOTE: some queries are made before the plugins have been loaded, and thus cannot be filtered with this method if (function_exists('apply_filters')) { $query = apply_filters('query', $query); } // initialise return $return_val = 0; $this->flush(); // Log how the function was called $this->func_call = "\$db->query(\"$query\")"; // Keep track of the last query for debug.. $this->last_query = $query; $caching = $this->can_cache($query); $cached = false; $data = false; $time_total = 0; if ($caching) { $cache_key = $this->_get_cache_key($query); $this->timer_start(); $cache = $this->_get_cache(); $data = $cache->get($cache_key); $time_total = $this->timer_stop(); } /** * Check if query was cached */ if (is_array($data)) { ++ $this->query_hits; $cached = true; /** * Set result from the cache */ $this->last_error = $data['last_error']; $this->last_query = $data['last_query']; $this->last_result = $data['last_result']; $this->col_info = $data['col_info']; $this->num_rows = $data['num_rows']; } else { ++ $this->num_queries; ++ $this->query_misses; // Perform the query via std mysql_query function.. $this->timer_start(); $this->result = @mysql_query($query, $this->dbh); $time_total = $this->timer_stop(); if (defined('SAVEQUERIES') && SAVEQUERIES) { $this->queries[] = array( $query, $time_total, $this->get_caller() ); } // If there is an error then take note of it.. if (($this->last_error = mysql_error($this->dbh))) { $this->print_error(); return false; } if (preg_match("/^\\s*(insert|delete|update|replace|alter) /i", $query)) { $this->rows_affected = mysql_affected_rows($this->dbh); // Take note of the insert_id if (preg_match("/^\\s*(insert|replace) /i", $query)) { $this->insert_id = mysql_insert_id($this->dbh); } // Return number of rows affected $return_val = $this->rows_affected; } else { $i = 0; while ($i < @mysql_num_fields($this->result)) { $this->col_info[$i] = @mysql_fetch_field($this->result); $i ++; } $num_rows = 0; while (($row = @mysql_fetch_object($this->result))) { $this->last_result[$num_rows] = $row; $num_rows ++; } @mysql_free_result($this->result); // Log number of rows the query returned $this->num_rows = $num_rows; // Return number of rows selected $return_val = $this->num_rows; if ($caching) { /** * Store result to the cache */ $data = array( 'last_error' => $this->last_error, 'last_query' => $this->last_query, 'last_result' => $this->last_result, 'col_info' => $this->col_info, 'num_rows' => $this->num_rows ); $cache = $this->_get_cache(); $cache->set($cache_key, $data, $this->_get_lifetime($query)); } } } if ($this->_config->get_boolean('dbcache.debug')) { $this->query_stats[] = array( 'query' => $query, 'caching' => $caching, 'cached' => $cached, 'time_total' => $time_total ); } $this->time_total += $time_total; return $return_val; } /** * Check if can cache sql * * @param string $sql * @return boolean */ function can_cache($sql) { /** * Skip if disabled */ if (! $this->_config->get_boolean('dbcache.enabled')) { return false; } /** * Skip if doing cron */ if (defined('DOING_CRON')) { return false; } /** * Skip if request URI is rejected */ if (! $this->_check_request_uri()) { return false; } /** * Skip if SQL is rejected */ if (! $this->_check_sql($sql)) { return false; } return true; } /** * Flushes cache * * @return boolean */ function flush_cache() { $cache = $this->_get_cache(); return $cache->flush(); } /** * Returns onject instance * * @return W3_Db */ function &instance() { static $instance = null; if ($instance === null) { $class = __CLASS__; $instance = & new $class(DB_USER, DB_PASSWORD, DB_NAME, DB_HOST); } return $instance; } /** * Returns debug info * * @return string */ function get_debug_info() { $debug_info = "', '-- >', trim($query['query']))); } } $debug_info .= '-->'; return $debug_info; } /** * Returns cache object * * @return W3_Cache_Base */ function &_get_cache() { static $cache = null; if ($cache === null) { $engine = $this->_config->get_string('dbcache.engine', 'memcached'); if ($engine == 'memcached') { $engineConfig = array( 'engine' => $this->_config->get_string('dbcache.memcached.engine', 'auto'), 'servers' => $this->_config->get_array('dbcache.memcached.servers') ); } else { $engineConfig = array(); } require_once W3TC_LIB_W3_DIR . '/Cache.php'; $cache = & W3_Cache::instance($engine, $engineConfig); } return $cache; } /** * Check SQL * * @param string $sql * @return boolean */ function _check_sql($sql) { $auto_reject_strings = array( 'insert', 'delete', 'update', 'replace', 'alter', 'set names', 'found_rows', $this->prefix . 'posts', $this->prefix . 'postsmeta' ); if (preg_match('@(' . implode('|', $auto_reject_strings) . ')@i', $sql)) { return false; } $reject_sql = $this->_config->get_array('dbcache.reject.sql'); foreach ($reject_sql as $expr) { $expr = trim($expr); if ($expr != '' && preg_match('@' . $expr . '@i', $sql)) { return false; } } return true; } /** * Check request URI * * @return boolean */ function _check_request_uri() { $auto_reject_uri = array( 'wp-admin', 'wp-login', 'wp-register', 'wp-signup' ); foreach ($auto_reject_uri as $uri) { if (strstr($_SERVER['REQUEST_URI'], $uri) !== false) { return false; } } $reject_uri = $this->_config->get_array('dbcache.reject.uri'); foreach ($reject_uri as $expr) { $expr = trim($expr); if ($expr != '' && preg_match('@' . $expr . '@i', $_SERVER['REQUEST_URI'])) { return false; } } return true; } /** * Returns cache key * * @param string $sql * @return string */ function _get_cache_key($sql) { $blog_id = w3_get_blog_id(); if (empty($blog_id)) { $blog_id = $_SERVER['HTTP_HOST']; } return sprintf('w3tc_%s_sql_%s', md5($blog_id), md5($sql)); } /** * Returns lifetime for SQL * * @param string $sql * @return integer */ function _get_lifetime($sql) { $config = array( '__default' => $this->_config->get_integer('dbcache.lifetime.default', 180), '_options' => $this->_config->get_integer('dbcache.lifetime.options', 180), '_links' => $this->_config->get_integer('dbcache.lifetime.links', 10800), '_terms' => $this->_config->get_integer('dbcache.lifetime.terms', 10800), '_user' => $this->_config->get_integer('dbcache.lifetime.user', 1800), '_post' => $this->_config->get_integer('dbcache.lifetime.post', 3600) ); $lifetime = $config['__default']; foreach ($config as $string => $ttl) { if (strstr($sql, $string) !== false) { $lifetime = $ttl; break; } } return $lifetime; } }