123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666 |
- <?php
- namespace Elgg;
- use Elgg\Database\Config;
- class Database {
-
- private $tablePrefix;
-
- private $dbLinks = array();
-
- private $queryCount = 0;
-
- private $queryCache = null;
-
- private $queryCacheSize = 50;
-
- private $delayedQueries = array();
-
- private $installed = false;
-
- private $config;
-
- private $logger;
-
- public function __construct(\Elgg\Database\Config $config, \Elgg\Logger $logger) {
- $this->logger = $logger;
- $this->config = $config;
- $this->tablePrefix = $config->getTablePrefix();
- $this->enableQueryCache();
- }
-
- public function getLink($type) {
- if (isset($this->dbLinks[$type])) {
- return $this->dbLinks[$type];
- } else if (isset($this->dbLinks['readwrite'])) {
- return $this->dbLinks['readwrite'];
- } else {
- $this->setupConnections();
- return $this->getLink($type);
- }
- }
-
- public function setupConnections() {
- if ($this->config->isDatabaseSplit()) {
- $this->establishLink('read');
- $this->establishLink('write');
- } else {
- $this->establishLink('readwrite');
- }
- }
-
- public function establishLink($dblinkname = "readwrite") {
- $conf = $this->config->getConnectionConfig($dblinkname);
-
- $this->dbLinks[$dblinkname] = mysql_connect($conf['host'], $conf['user'], $conf['password'], true);
- if (!$this->dbLinks[$dblinkname]) {
- $msg = "Elgg couldn't connect to the database using the given credentials. Check the settings file.";
- throw new \DatabaseException($msg);
- }
- if (!mysql_select_db($conf['database'], $this->dbLinks[$dblinkname])) {
- $msg = "Elgg couldn't select the database '{$conf['database']}'. Please check that the database is created and you have access to it.";
- throw new \DatabaseException($msg);
- }
-
- mysql_query("SET NAMES utf8", $this->dbLinks[$dblinkname]);
- }
-
- public function getData($query, $callback = '') {
- return $this->getResults($query, $callback, false);
- }
-
- public function getDataRow($query, $callback = '') {
- return $this->getResults($query, $callback, true);
- }
-
- public function insertData($query) {
- $this->logger->log("DB query $query", \Elgg\Logger::INFO);
- $dblink = $this->getLink('write');
- $this->invalidateQueryCache();
- if ($this->executeQuery("$query", $dblink)) {
- return mysql_insert_id($dblink);
- }
- return false;
- }
-
- public function updateData($query, $getNumRows = false) {
- $this->logger->log("DB query $query", \Elgg\Logger::INFO);
- $dblink = $this->getLink('write');
- $this->invalidateQueryCache();
- if ($this->executeQuery("$query", $dblink)) {
- if ($getNumRows) {
- return mysql_affected_rows($dblink);
- } else {
- return true;
- }
- }
- return false;
- }
-
- public function deleteData($query) {
- $this->logger->log("DB query $query", \Elgg\Logger::INFO);
- $dblink = $this->getLink('write');
- $this->invalidateQueryCache();
- if ($this->executeQuery("$query", $dblink)) {
- return mysql_affected_rows($dblink);
- }
- return false;
- }
-
- public function fingerprintCallback($callback) {
- if (is_string($callback)) {
- return $callback;
- }
- if (is_object($callback)) {
- return spl_object_hash($callback) . "::__invoke";
- }
- if (is_array($callback)) {
- if (is_string($callback[0])) {
- return "{$callback[0]}::{$callback[1]}";
- }
- return spl_object_hash($callback[0]) . "::{$callback[1]}";
- }
-
- return "";
- }
-
- protected function getResults($query, $callback = null, $single = false) {
-
-
-
- $query_id = (int)$single . $query . '|';
- if ($callback) {
- $is_callable = is_callable($callback);
- if ($is_callable) {
- $query_id .= $this->fingerprintCallback($callback);
- } else {
-
- $callback = null;
- }
- } else {
- $is_callable = false;
- }
-
- $hash = md5($query_id);
-
- if ($this->queryCache) {
- if (isset($this->queryCache[$hash])) {
- $this->logger->log("DB query $query results returned from cache (hash: $hash)", \Elgg\Logger::INFO);
- return $this->queryCache[$hash];
- }
- }
- $dblink = $this->getLink('read');
- $return = array();
- if ($result = $this->executeQuery("$query", $dblink)) {
- while ($row = mysql_fetch_object($result)) {
- if ($is_callable) {
- $row = call_user_func($callback, $row);
- }
- if ($single) {
- $return = $row;
- break;
- } else {
- $return[] = $row;
- }
- }
- }
- if (empty($return)) {
- $this->logger->log("DB query $query returned no results.", \Elgg\Logger::INFO);
- }
-
- if ($this->queryCache) {
- $this->queryCache[$hash] = $return;
- $this->logger->log("DB query $query results cached (hash: $hash)", \Elgg\Logger::INFO);
- }
- return $return;
- }
-
- public function executeQuery($query, $dblink) {
- if ($query == null) {
- throw new \DatabaseException("Query cannot be null");
- }
- if (!is_resource($dblink)) {
- throw new \DatabaseException("Connection to database was lost.");
- }
- $this->queryCount++;
- $result = mysql_query($query, $dblink);
- if (mysql_errno($dblink)) {
- throw new \DatabaseException(mysql_error($dblink) . "\n\n QUERY: $query");
- }
- return $result;
- }
-
- public function runSqlScript($scriptlocation) {
- $script = file_get_contents($scriptlocation);
- if ($script) {
- $errors = array();
-
- $script = preg_replace('/^(?:--|#) .*$/m', '', $script);
-
- $sql_statements = preg_split('/;[\n\r]+/', "$script\n");
- foreach ($sql_statements as $statement) {
- $statement = trim($statement);
- $statement = str_replace("prefix_", $this->tablePrefix, $statement);
- if (!empty($statement)) {
- try {
- $this->updateData($statement);
- } catch (\DatabaseException $e) {
- $errors[] = $e->getMessage();
- }
- }
- }
- if (!empty($errors)) {
- $errortxt = "";
- foreach ($errors as $error) {
- $errortxt .= " {$error};";
- }
- $msg = "There were a number of issues: " . $errortxt;
- throw new \DatabaseException($msg);
- }
- } else {
- $msg = "Elgg couldn't find the requested database script at " . $scriptlocation . ".";
- throw new \DatabaseException($msg);
- }
- }
-
- public function registerDelayedQuery($query, $type, $handler = "") {
- if (!is_resource($type) && $type != 'read' && $type != 'write') {
- return false;
- }
-
- $delayed_query = array();
- $delayed_query['q'] = $query;
- $delayed_query['l'] = $type;
- $delayed_query['h'] = $handler;
- $this->delayedQueries[] = $delayed_query;
- return true;
- }
-
- public function executeDelayedQueries() {
- foreach ($this->delayedQueries as $query_details) {
- try {
- $link = $query_details['l'];
- if ($link == 'read' || $link == 'write') {
- $link = $this->getLink($link);
- } elseif (!is_resource($link)) {
- $msg = "Link for delayed query not valid resource or db_link type. Query: {$query_details['q']}";
- $this->logger->log($msg, \Elgg\Logger::WARNING);
- }
- $result = $this->executeQuery($query_details['q'], $link);
- if ((isset($query_details['h'])) && (is_callable($query_details['h']))) {
- $query_details['h']($result);
- }
- } catch (\DatabaseException $e) {
-
- $this->logger->log($e, \Elgg\Logger::ERROR);
- }
- }
- }
-
- public function enableQueryCache() {
- if ($this->config->isQueryCacheEnabled() && $this->queryCache === null) {
-
- $this->queryCache = new \Elgg\Cache\LRUCache($this->queryCacheSize);
- }
- }
-
- public function disableQueryCache() {
- $this->queryCache = null;
- }
-
- protected function invalidateQueryCache() {
- if ($this->queryCache) {
- $this->queryCache->clear();
- $this->logger->log("Query cache invalidated", \Elgg\Logger::INFO);
- }
- }
-
- public function assertInstalled() {
- if ($this->installed) {
- return;
- }
- try {
- $dblink = $this->getLink('read');
- mysql_query("SELECT value FROM {$this->tablePrefix}datalists WHERE name = 'installed'", $dblink);
- if (mysql_errno($dblink) > 0) {
- throw new \DatabaseException();
- }
- } catch (\DatabaseException $e) {
- throw new \InstallationException("Unable to handle this request. This site is not configured or the database is down.");
- }
- $this->installed = true;
- }
-
- public function getQueryCount() {
- return $this->queryCount;
- }
-
- public function getTablePrefix() {
- return $this->tablePrefix;
- }
-
- public function sanitizeInt($value, $signed = true) {
- $value = (int) $value;
- if ($signed === false) {
- if ($value < 0) {
- $value = 0;
- }
- }
- return $value;
- }
-
- public function sanitizeString($value) {
-
- if (isset($this->dbLinks['read'])) {
- return mysql_real_escape_string($value, $this->dbLinks['read']);
- }
- return mysql_real_escape_string($value);
- }
-
- public function getServerVersion($type) {
- return mysql_get_server_info($this->getLink($type));
- }
- }
|