BxDolDb.php 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796
  1. <?php defined('BX_DOL') or defined('BX_DOL_INSTALL') or die('hack attempt');
  2. /**
  3. * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
  4. * CC-BY License - http://creativecommons.org/licenses/by/3.0/
  5. *
  6. * @defgroup DolphinCore Dolphin Core
  7. * @{
  8. */
  9. class BxDolDb extends BxDol implements iBxDolSingleton {
  10. var $error_checking = true;
  11. var $error_message;
  12. var $host, $port, $socket, $dbname, $user, $password, $link;
  13. var $current_res, $current_arr_type;
  14. var $oDbCacheObject = null;
  15. /**
  16. * set database parameters and connect to it
  17. */
  18. protected function BxDolDb($aDbConf = false) {
  19. if (isset($GLOBALS['bxDolClasses'][get_class($this)]))
  20. trigger_error ('Multiple instances are not allowed for the class: ' . get_class($this), E_USER_ERROR);
  21. parent::BxDol();
  22. if (false === $aDbConf) {
  23. $this->host = BX_DATABASE_HOST;
  24. $this->port = BX_DATABASE_PORT;
  25. $this->socket = BX_DATABASE_SOCK;
  26. $this->dbname = BX_DATABASE_NAME;
  27. $this->user = BX_DATABASE_USER;
  28. $this->password = BX_DATABASE_PASS;
  29. } else {
  30. $this->host = $aDbConf['host'];
  31. $this->port = $aDbConf['port'];
  32. $this->socket = $aDbConf['sock'];
  33. $this->dbname = $aDbConf['name'];
  34. $this->user = $aDbConf['user'];
  35. $this->password = $aDbConf['pwd'];
  36. $this->error_checking = isset($aDbConf['error_checking']) ? $aDbConf['error_checking'] : true;
  37. }
  38. $this->current_arr_type = MYSQL_ASSOC;
  39. // connect to db automatically
  40. if (empty($GLOBALS['bx_db_link'])) {
  41. $this->connect();
  42. $GLOBALS['gl_db_cache'] = array();
  43. } else {
  44. $this->link = $GLOBALS['bx_db_link'];
  45. }
  46. }
  47. /**
  48. * Prevent cloning the instance
  49. */
  50. public function __clone() {
  51. if (isset($GLOBALS['bxDolClasses'][get_class($this)]))
  52. trigger_error('Clone is not allowed for the class: ' . get_class($this), E_USER_ERROR);
  53. }
  54. public function __get($sName)
  55. {
  56. if ('oParams' == $sName) {
  57. bx_import('BxDolParams');
  58. return BxDolParams::getInstance($this);
  59. }
  60. $aTrace = debug_backtrace();
  61. trigger_error('Undefined property via __get(): ' . $sName . ' in ' . $aTrace[0]['file'] . ' on line ' . $aTrace[0]['line'], E_USER_NOTICE);
  62. return null;
  63. }
  64. public function __isset($sName)
  65. {
  66. if ('oParams' == $sName)
  67. return true;
  68. return false;
  69. }
  70. /**
  71. * Get singleton instance of the class
  72. */
  73. public static function getInstance($aDbConf = false, &$sError = null) {
  74. if (!isset($GLOBALS['bxDolClasses'][__CLASS__])) {
  75. $o = new BxDolDb($aDbConf);
  76. $sErrorMessage = $o->connect();
  77. if ($sErrorMessage) {
  78. if ($sError !== null)
  79. $sError = $sErrorMessage;
  80. return null;
  81. } else {
  82. $GLOBALS['bxDolClasses'][__CLASS__] = $o;
  83. }
  84. }
  85. return $GLOBALS['bxDolClasses'][__CLASS__];
  86. }
  87. /**
  88. * connect to database with appointed parameters
  89. */
  90. function connect()
  91. {
  92. $full_host = $this->host;
  93. $full_host .= $this->port ? ':'.$this->port : '';
  94. $full_host .= $this->socket ? ':'.$this->socket : '';
  95. $this->link = @mysql_pconnect($full_host, $this->user, $this->password);
  96. if (!$this->link)
  97. return 'Database connect failed';
  98. if (!$this->select_db())
  99. return 'Database select failed';
  100. mysql_query("SET NAMES 'utf8'", $this->link);
  101. mysql_query("SET sql_mode = ''", $this->link);
  102. $GLOBALS['bx_db_link'] = $this->link;
  103. return '';
  104. }
  105. function select_db()
  106. {
  107. return @mysql_select_db($this->dbname, $this->link);
  108. }
  109. /**
  110. * close mysql connection
  111. */
  112. function close()
  113. {
  114. mysql_close($this->link);
  115. }
  116. /**
  117. * get mysql server info
  118. */
  119. function getServerInfo()
  120. {
  121. return mysql_get_server_info($this->link);
  122. }
  123. /**
  124. * get mysql option
  125. */
  126. function getOption($sName)
  127. {
  128. return $this->getOne("SELECT @@{$sName}");
  129. }
  130. /**
  131. * execute sql query and return one row result
  132. */
  133. function getRow($query, $arr_type = MYSQL_ASSOC)
  134. {
  135. if(!$query)
  136. return array();
  137. if($arr_type != MYSQL_ASSOC && $arr_type != MYSQL_NUM && $arr_type != MYSQL_BOTH)
  138. $arr_type = MYSQL_ASSOC;
  139. $res = $this->res ($query);
  140. $arr_res = array();
  141. if($res && mysql_num_rows($res))
  142. {
  143. $arr_res = mysql_fetch_array($res, $arr_type);
  144. mysql_free_result($res);
  145. }
  146. return $arr_res;
  147. }
  148. /**
  149. * execute sql query and return a column as result
  150. */
  151. function getColumn($sQuery) {
  152. if(!$sQuery)
  153. return array();
  154. $rResult = $this->res($sQuery);
  155. $aResult = array();
  156. if($rResult) {
  157. while($aRow = mysql_fetch_array($rResult, MYSQL_NUM))
  158. $aResult[] = $aRow[0];
  159. mysql_free_result($rResult);
  160. }
  161. return $aResult;
  162. }
  163. /**
  164. * execute sql query and return one value result
  165. */
  166. function getOne($query, $index = 0)
  167. {
  168. if(!$query)
  169. return false;
  170. $res = $this->res ($query);
  171. $arr_res = array();
  172. if($res && mysql_num_rows($res))
  173. $arr_res = mysql_fetch_array($res);
  174. if(count($arr_res))
  175. return $arr_res[$index];
  176. else
  177. return false;
  178. }
  179. /**
  180. * execute sql query and return the first row of result
  181. * and keep $array type and poiter to all data
  182. */
  183. function getFirstRow($query, $arr_type = MYSQL_ASSOC)
  184. {
  185. if(!$query)
  186. return array();
  187. if($arr_type != MYSQL_ASSOC && $arr_type != MYSQL_NUM)
  188. $this->current_arr_type = MYSQL_ASSOC;
  189. else
  190. $this->current_arr_type = $arr_type;
  191. $this->current_res = $this->res ($query);
  192. $arr_res = array();
  193. if($this->current_res && mysql_num_rows($this->current_res))
  194. $arr_res = mysql_fetch_array($this->current_res, $this->current_arr_type);
  195. return $arr_res;
  196. }
  197. /**
  198. * return next row of pointed last getFirstRow calling data
  199. */
  200. function getNextRow()
  201. {
  202. $arr_res = mysql_fetch_array($this->current_res, $this->current_arr_type);
  203. if($arr_res)
  204. return $arr_res;
  205. else
  206. {
  207. mysql_free_result($this->current_res);
  208. $this->current_arr_type = MYSQL_ASSOC;
  209. return array();
  210. }
  211. }
  212. /**
  213. * return number of affected rows in current mysql result
  214. */
  215. function getNumRows($res = false)
  216. {
  217. if ($res)
  218. return (int)@mysql_num_rows($res);
  219. elseif (!$this->current_res)
  220. return (int)@mysql_num_rows($this->current_res);
  221. else
  222. return 0;
  223. }
  224. /**
  225. * execute any query return number of rows affected/false
  226. */
  227. function getAffectedRows()
  228. {
  229. return mysql_affected_rows($this->link);
  230. }
  231. /**
  232. * execute any query return number of rows affected/false
  233. */
  234. function query($query)
  235. {
  236. $res = $this->res($query);
  237. if ($res)
  238. return mysql_affected_rows($this->link);
  239. return false;
  240. }
  241. /**
  242. * execute any query
  243. */
  244. function res($query, $error_checking = true)
  245. {
  246. if(!$query)
  247. return false;
  248. if (isset($GLOBALS['bx_profiler'])) $GLOBALS['bx_profiler']->beginQuery($query);
  249. $res = @mysql_query($query, $this->link);
  250. if (false === $res)
  251. $this->error_message = @mysql_error($this->link); // we need to remeber last error message since mysql_ping will reset it on the next line !
  252. else
  253. $this->error_message = '';
  254. if (!$res && !@mysql_ping($this->link)) { // if mysql connection is lost - reconnect and try again
  255. @mysql_close($this->link);
  256. $sErrorMessage = $this->connect();
  257. if ($sErrorMessage)
  258. $this->error($sErrorMessage, true);
  259. $res = mysql_query($query, $this->link);
  260. }
  261. if (isset($GLOBALS['bx_profiler'])) $GLOBALS['bx_profiler']->endQuery($res);
  262. if (!$res && $error_checking)
  263. $this->error('Database query error', false, $query);
  264. return $res;
  265. }
  266. /**
  267. * execute sql query and return table of records as result
  268. */
  269. function getAll($query, $arr_type = MYSQL_ASSOC)
  270. {
  271. if(!$query)
  272. return array();
  273. if($arr_type != MYSQL_ASSOC && $arr_type != MYSQL_NUM && $arr_type != MYSQL_BOTH)
  274. $arr_type = MYSQL_ASSOC;
  275. $res = $this->res ($query);
  276. $arr_res = array();
  277. if($res)
  278. {
  279. while($row = mysql_fetch_array($res, $arr_type))
  280. $arr_res[] = $row;
  281. mysql_free_result($res);
  282. }
  283. return $arr_res;
  284. }
  285. /**
  286. * execute sql query and return table of records as result
  287. */
  288. function fillArray($res, $arr_type = MYSQL_ASSOC)
  289. {
  290. if(!$res)
  291. return array();
  292. if($arr_type != MYSQL_ASSOC && $arr_type != MYSQL_NUM && $arr_type != MYSQL_BOTH)
  293. $arr_type = MYSQL_ASSOC;
  294. $arr_res = array();
  295. while($row = mysql_fetch_array($res, $arr_type))
  296. $arr_res[] = $row;
  297. mysql_free_result($res);
  298. return $arr_res;
  299. }
  300. /**
  301. * execute sql query and return table of records as result
  302. */
  303. function getAllWithKey($query, $sFieldKey)
  304. {
  305. if(!$query)
  306. return array();
  307. $res = $this->res ($query);
  308. $arr_res = array();
  309. if($res)
  310. {
  311. while($row = mysql_fetch_array($res, MYSQL_ASSOC))
  312. {
  313. $arr_res[$row[$sFieldKey]] = $row;
  314. }
  315. mysql_free_result($res);
  316. }
  317. return $arr_res;
  318. }
  319. /**
  320. * execute sql query and return table of records as result
  321. */
  322. function getPairs($query, $sFieldKey, $sFieldValue, $arr_type = MYSQL_ASSOC)
  323. {
  324. if(!$query)
  325. return array();
  326. $res = $this->res ($query);
  327. $arr_res = array();
  328. if($res)
  329. {
  330. while($row = mysql_fetch_array($res, MYSQL_ASSOC))
  331. {
  332. $arr_res[$row[$sFieldKey]] = $row[$sFieldValue];
  333. }
  334. mysql_free_result($res);
  335. }
  336. return $arr_res;
  337. }
  338. function lastId()
  339. {
  340. return mysql_insert_id($this->link);
  341. }
  342. function getErrorMessage ()
  343. {
  344. $s = mysql_error($this->link);
  345. if ($s)
  346. return $s;
  347. else
  348. return $this->error_message;
  349. }
  350. function error($text, $isForceErrorChecking = false, $sSqlQuery = '')
  351. {
  352. if ($this->error_checking || $isForceErrorChecking)
  353. $this->genMySQLErr ($text, $sSqlQuery);
  354. else
  355. $this->log($text . ': ' . $this->getErrorMessage());
  356. }
  357. function isParam($sName, $bCache = true) {
  358. return $this->oParams->exists($sName, $bCache);
  359. }
  360. function addParam($sName, $sValue, $iKateg, $sDesc, $sType) {
  361. return $this->oParams->add($sName, $sValue, $iKateg, $sDesc, $sType);
  362. }
  363. function getParam($sName, $bCache = true) {
  364. return $this->oParams->get($sName, $bCache);
  365. }
  366. function setParam($sName, $sValue ) {
  367. $this->oParams->set($sName, $sValue);
  368. return true;
  369. }
  370. function listTables() {
  371. return mysql_list_tables($GLOBALS['db']['db'], $this->link);
  372. //return mysql_list_tables($GLOBALS['db']['db'], $this->link) or $this->error('Database get encoding error');
  373. }
  374. function getFields($sTable) {
  375. $rFields = mysql_list_fields($this->dbname, $sTable, $this->link);
  376. $iFields = mysql_num_fields($rFields);
  377. $aResult = array('original' => array(), 'uppercase' => array());
  378. for($i = 0; $i < $iFields; $i++) {
  379. $sName = mysql_field_name($rFields, $i);
  380. $aResult['original'][] = $sName;
  381. $aResult['uppercase'][] = strtoupper($sName);
  382. }
  383. return $aResult;
  384. }
  385. function isFieldExists($sTable, $sFieldName) {
  386. $aFields = $this->getFields($sTable);
  387. return in_array(strtoupper($sFieldName), $aFields['uppercase']);
  388. }
  389. function getEncoding() {
  390. return mysql_client_encoding($this->link) or $this->error('Database get encoding error');
  391. }
  392. function genMySQLErr( $out, $query ='' ) {
  393. $sParamsOutput = false;
  394. $sFoundError = '';
  395. $aBackTrace = debug_backtrace();
  396. unset( $aBackTrace[0] );
  397. if( $query )
  398. {
  399. //try help to find error
  400. $aFoundError = array();
  401. foreach( $aBackTrace as $aCall )
  402. {
  403. // truncating global settings since it repeated many times and output it separately
  404. if (isset($aCall['object']) && property_exists($aCall['object'], 'oParams') && property_exists($aCall['object']->oParams, '_aParams')) {
  405. if (false === $sParamsOutput)
  406. $sParamsOutput = var_export($aCall['object']->oParams->_aParams, true);
  407. $aCall['object']->oParams->_aParams = '[truncated]';
  408. }
  409. if (isset($aCall['args']) && is_array($aCall['args']))
  410. {
  411. foreach( $aCall['args'] as $argNum => $argVal )
  412. {
  413. if( is_string($argVal) and strcmp( $argVal, $query ) == 0 )
  414. {
  415. $aFoundError['file'] = isset($aCall['file']) ? $aCall['file'] : (isset($aCall['class']) ? 'class: ' . $aCall['class'] : 'undefined');
  416. $aFoundError['line'] = isset($aCall['line']) ? $aCall['line'] : 'undefined';
  417. $aFoundError['function'] = $aCall['function'];
  418. $aFoundError['arg'] = $argNum;
  419. }
  420. }
  421. }
  422. }
  423. if( $aFoundError )
  424. {
  425. $sFoundError = <<<EOJ
  426. Found error in the file '<b>{$aFoundError['file']}</b>' at line <b>{$aFoundError['line']}</b>.<br />
  427. Called '<b>{$aFoundError['function']}</b>' function with erroneous argument #<b>{$aFoundError['arg']}</b>.<br /><br />
  428. EOJ;
  429. }
  430. }
  431. bx_import('BxDolConfig');
  432. if (BxDolConfig::getInstance()->get('db', 'visual_processing')) {
  433. ?>
  434. <div style="border:2px solid red;padding:4px;width:600px;margin:0px auto;">
  435. <div style="text-align:center;background-color:red;color:white;font-weight:bold;">Error</div>
  436. <div style="text-align:center;"><?=$out?></div>
  437. <?
  438. if(BxDolConfig::getInstance()->get('db', 'debug_mode')) {
  439. if( strlen( $query ) )
  440. echo "<div><b>Query:</b><br />{$query}</div>";
  441. if ($this->link)
  442. echo '<div><b>Mysql error:</b><br />' . $this->getErrorMessage() . '</div>';
  443. echo '<div style="overflow:scroll;height:300px;border:1px solid gray;">';
  444. echo $sFoundError;
  445. echo "<b>Debug backtrace:</b><br />";
  446. $sBackTrace = print_r($aBackTrace, true);
  447. $sBackTrace = str_replace('[password] => ' . BX_DATABASE_PASS, '[password] => *****', $sBackTrace);
  448. $sBackTrace = str_replace('[user] => ' . BX_DATABASE_USER, '[user] => *****', $sBackTrace);
  449. echo '<pre>' . $sBackTrace . '</pre>';
  450. if ($sParamsOutput) {
  451. echo '<hr />';
  452. echo "<b>Settings:</b><br />";
  453. echo '<pre>' . htmlspecialchars_adv($sParamsOutput) . '</pre>';
  454. }
  455. echo "<b>Called script:</b> " . $_SERVER['PHP_SELF'] . "<br />";
  456. echo "<b>Request parameters:</b><br />";
  457. echoDbg( $_REQUEST );
  458. echo '</div>';
  459. }
  460. ?>
  461. </div>
  462. <?
  463. }
  464. else
  465. echo $out;
  466. if(BxDolConfig::getInstance()->get('db', 'error_remort_by_email')) {
  467. $sSiteTitle = getParam('site_title');
  468. $sMailBody = "Database error in " . $sSiteTitle . "<br /><br /> \n";
  469. if( strlen( $query ) )
  470. $sMailBody .= "Query: <pre>" . htmlspecialchars_adv($query) . "</pre> ";
  471. if ($this->link)
  472. $sMailBody .= "Mysql error: " . $this->getErrorMessage() . "<br /><br /> ";
  473. $sMailBody .= $sFoundError. '<br /> ';
  474. $sBackTrace = print_r($aBackTrace, true);
  475. $sBackTrace = str_replace('[password] => ' . BX_DATABASE_PASS, '[password] => *****', $sBackTrace);
  476. $sBackTrace = str_replace('[user] => ' . BX_DATABASE_USER, '[user] => *****', $sBackTrace);
  477. $sMailBody .= "Debug backtrace:\n <pre>" . htmlspecialchars_adv($sBackTrace) . "</pre> ";
  478. if ($sParamsOutput)
  479. $sMailBody .= "<hr />Settings:\n <pre>" . htmlspecialchars_adv($sParamsOutput) . "</pre> ";
  480. $sMailBody .= "<hr />Called script: " . $_SERVER['PHP_SELF'] . "<br /> ";
  481. $sMailBody .= "<hr />Request parameters: <pre>" . print_r( $_REQUEST, true ) . " </pre>";
  482. $sMailBody .= "--\nAuto-report system\n";
  483. sendMail(getParam('site_email_bug_report'), "Database error in " . $sSiteTitle, $sMailBody, 0, array(), BX_EMAIL_SYSTEM, 'html', true);
  484. }
  485. exit;
  486. }
  487. function setErrorChecking ($b) {
  488. $this->error_checking = $b;
  489. }
  490. function getDbCacheObject () {
  491. if ($this->oDbCacheObject != null) {
  492. return $this->oDbCacheObject;
  493. } else {
  494. $sEngine = getParam('sys_db_cache_engine');
  495. $this->oDbCacheObject = bx_instance ('BxDolCache'.$sEngine);
  496. if (!$this->oDbCacheObject->isAvailable())
  497. $this->oDbCacheObject = bx_instance ('BxDolCacheFile');
  498. return $this->oDbCacheObject;
  499. }
  500. }
  501. function genDbCacheKey ($sName) {
  502. return 'db_' . $sName . '_' . bx_site_hash() . '.php';
  503. }
  504. function fromCache ($sName, $sFunc) {
  505. $aArgs = func_get_args();
  506. array_shift ($aArgs); // shift $sName
  507. array_shift ($aArgs); // shift $sFunc
  508. if (!getParam('sys_db_cache_enable'))
  509. return call_user_func_array (array ($this, $sFunc), $aArgs); // pass other function parameters as database function parameters
  510. $oCache = $this->getDbCacheObject ();
  511. $sKey = $this->genDbCacheKey($sName);
  512. $mixedRet = $oCache->getData($sKey);
  513. if ($mixedRet !== null) {
  514. return $mixedRet;
  515. } else {
  516. $mixedRet = call_user_func_array (array ($this, $sFunc), $aArgs); // pass other function parameters as database function parameters
  517. $oCache->setData($sKey, $mixedRet);
  518. }
  519. return $mixedRet;
  520. }
  521. function cleanCache ($sName) {
  522. if (!getParam('sys_db_cache_enable'))
  523. return true;
  524. $oCache = $this->getDbCacheObject ();
  525. $sKey = $this->genDbCacheKey($sName);
  526. return $oCache->delData($sKey);
  527. }
  528. function & fromMemory ($sName, $sFunc) {
  529. if (array_key_exists($sName, $GLOBALS['gl_db_cache'])) {
  530. return $GLOBALS['gl_db_cache'][$sName];
  531. } else {
  532. $aArgs = func_get_args();
  533. array_shift ($aArgs); // shift $sName
  534. array_shift ($aArgs); // shift $sFunc
  535. $GLOBALS['gl_db_cache'][$sName] = call_user_func_array (array ($this, $sFunc), $aArgs); // pass other function parameters as database function parameters
  536. return $GLOBALS['gl_db_cache'][$sName];
  537. }
  538. }
  539. function cleanMemory ($sName) {
  540. if (isset($GLOBALS['gl_db_cache'][$sName])) {
  541. unset($GLOBALS['gl_db_cache'][$sName]);
  542. return true;
  543. }
  544. return false;
  545. }
  546. /**
  547. * It escapes string to pass to mysql query.
  548. * Try to use "prepare" function always (@see BxDolDb::prepare), use "escape" only if "prepare" function is not possible at all.
  549. * Also consider using "implode_escape" function (@see BxDolDb::implode_escape).
  550. *
  551. * @param string $s string to escape
  552. * @return escaped string whcich is ready to pass to SQL query.
  553. */
  554. function escape ($s) {
  555. return mysql_real_escape_string($s, $this->link);
  556. }
  557. /**
  558. * This function is usefull when you need to form array of parameters to pass to IN(...) SQL construction.
  559. * Example:
  560. * @code
  561. * $a = array(2, 4.5, 'apple', 'car');
  562. * $s = "SELECT * FROM `t` WHERE `a` IN (" . $oDb->implode_escape($a) . ")";
  563. * echo $s; // outputs: SELECT * FROM `t` WHERE `a` IN (2, 4.5, 'apple', 'car')
  564. * @endcode
  565. *
  566. * @param $mixed array or parameters or just one paramter
  567. * @return string which is ready to pass to IN(...) SQL construction
  568. */
  569. function implode_escape ($mixed) {
  570. if (is_array($mixed)) {
  571. $s = '';
  572. foreach ($mixed as $v)
  573. $s .= (is_numeric($v) ? $v : "'" . mysql_real_escape_string($v, $this->link) . "'") . ',';
  574. if ($s)
  575. return substr($s, 0, -1);
  576. else
  577. return 'NULL';
  578. }
  579. return is_numeric($mixed) ? $mixed : ($mixed ? "'" . mysql_real_escape_string($mixed, $this->link) . "'" : 'NULL');
  580. }
  581. /**
  582. * @deprecated
  583. */
  584. function unescape ($mixed) {
  585. if (is_array($mixed)) {
  586. foreach ($mixed as $k => $v)
  587. $mixed[$k] = $this->getOne("SELECT '$v'");
  588. return $mixed;
  589. } else {
  590. return $this->getOne("SELECT '$mixed'");
  591. }
  592. }
  593. /**
  594. * Prepare SQL query before execution if some arguments are need to be passed to it.
  595. * All parameters marked with question (?) symbol in SQL query are replaced with parameters passed after SQL query parameter.
  596. * Parameters are properly excaped and surrounded by qutes if needed.
  597. * Example:
  598. * @code
  599. * $sSql = $oDb->prepare("SELECT `a`, `b` from `t` WHERE `c` = ? and `d` = ?", 12, 'aa');
  600. * echo $sSql;// outputs: SELECT `a`, `b` from `t` WHERE `c` = 12 and `d` = 'aa'
  601. * $a = $oDb->getAll($sSql);
  602. * @endcode
  603. *
  604. * @param string $sQuery SQL query, parameters for replacing are marked with ? symbol
  605. * @param mixed $mixed any number if parameters to replace, number of parameters whould match number of ? symbols in SQL query
  606. * @return string with SQL query ready for execution
  607. */
  608. function prepare ($sQuery) {
  609. $aArgs = func_get_args();
  610. $sQuery = array_shift($aArgs);
  611. $iPos = 0;
  612. foreach ($aArgs as $mixedArg) {
  613. if (is_null($mixedArg))
  614. $s = 'NULL';
  615. elseif (is_numeric($mixedArg))
  616. $s = $mixedArg;
  617. else
  618. $s = "'" . mysql_real_escape_string($mixedArg, $this->link) . "'";
  619. $i = bx_mb_strpos($sQuery, '?', $iPos);
  620. $sQuery = bx_mb_substr_replace($sQuery, $s, $i, 1);
  621. $iPos = $i + get_mb_len($s);
  622. }
  623. return $sQuery;
  624. }
  625. function log ($s) {
  626. return file_put_contents(BX_DIRECTORY_PATH_ROOT . 'tmp/db.err.log', date('Y-m-d H:i:s') . "\t" . $s . "\n", FILE_APPEND);
  627. }
  628. function executeSQL($sPath, $aReplace = array (), $isBreakOnError = true) {
  629. if(!file_exists($sPath) || !($rHandler = fopen($sPath, "r")))
  630. return array(array ('query' => "fopen($sPath, 'r')", 'error' => 'file not found or permission denied'));
  631. $sQuery = "";
  632. $sDelimiter = ';';
  633. $aResult = array();
  634. while(!feof($rHandler)) {
  635. $sStr = trim(fgets($rHandler));
  636. if(empty($sStr) || $sStr[0] == "" || $sStr[0] == "#" || ($sStr[0] == "-" && $sStr[1] == "-"))
  637. continue;
  638. //--- Change delimiter ---//
  639. if(strpos($sStr, "DELIMITER //") !== false || strpos($sStr, "DELIMITER ;") !== false) {
  640. $sDelimiter = trim(str_replace('DELIMITER', '', $sStr));
  641. continue;
  642. }
  643. $sQuery .= $sStr;
  644. //--- Check for multiline query ---//
  645. if(substr($sStr, -strlen($sDelimiter)) != $sDelimiter)
  646. continue;
  647. //--- Execute query ---//
  648. if ($aReplace)
  649. $sQuery = str_replace($aReplace['from'], $aReplace['to'], $sQuery);
  650. if($sDelimiter != ';')
  651. $sQuery = str_replace($sDelimiter, "", $sQuery);
  652. $rResult = $this->res(trim($sQuery), false);
  653. if(!$rResult) {
  654. $aResult[] = array('query' => $sQuery, 'error' => $this->getErrorMessage());
  655. if ($isBreakOnError)
  656. break;
  657. }
  658. $sQuery = "";
  659. }
  660. fclose($rHandler);
  661. return empty($aResult) ? true : $aResult;
  662. }
  663. }
  664. /** @} */