database.lib.php 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. /**
  4. * This is the main database library for Chamilo.
  5. * Include/require it in your code to use its functionality.
  6. *
  7. * This library now uses a Doctrine DBAL Silex service provider
  8. *
  9. * @package chamilo.library
  10. */
  11. /**
  12. * Database class definition
  13. * @package chamilo.database
  14. */
  15. class Database
  16. {
  17. /**
  18. * The main connection
  19. *
  20. * @var \Doctrine\DBAL\Connection
  21. */
  22. private static $db;
  23. /**
  24. * Read connection
  25. *
  26. * @var \Doctrine\DBAL\Connection
  27. */
  28. private static $connectionRead;
  29. /**
  30. * Write connection
  31. *
  32. * @var \Doctrine\DBAL\Connection
  33. */
  34. private static $connectionWrite;
  35. /**
  36. * Constructor
  37. *
  38. * @param $db \Doctrine\DBAL\Connection
  39. * @param array $dbs
  40. */
  41. public function __construct($db, $dbs)
  42. {
  43. self::$db = $db;
  44. // Using read/write connections see the services.php file
  45. self::$connectionRead = isset($dbs['db_read']) ? $dbs['db_read'] : $db;
  46. self::$connectionWrite = isset($dbs['db_write']) ? $dbs['db_write'] : $db;
  47. }
  48. /**
  49. * Return current connection
  50. * @return \Doctrine\DBAL\Connection
  51. */
  52. public function getConnection()
  53. {
  54. return self::$db;
  55. }
  56. /* Variable use only in the installation process to log errors. See the Database::query function */
  57. // static $log_queries = false;
  58. /**
  59. * Returns the name of the main database.
  60. * @return string
  61. */
  62. public static function get_main_database()
  63. {
  64. return self::$db->getDatabase();
  65. }
  66. /**
  67. * The glue is the string needed between database and table.
  68. * The trick is: in multiple databases, this is a period (with backticks).
  69. * In single database, this can be e.g. an underscore so we just fake
  70. * there are multiple databases and the code can be written independent
  71. * of the single / multiple database setting.
  72. * @return string
  73. */
  74. public static function get_database_glue()
  75. {
  76. return `.`;
  77. }
  78. /*
  79. Table name methods
  80. Use these methods to get table names for queries,
  81. instead of constructing them yourself.
  82. Backticks automatically surround the result,
  83. e.g. COURSE_NAME.link
  84. so the queries can look cleaner.
  85. Example:
  86. $table = Database::get_course_table(TABLE_DOCUMENT);
  87. $sql_query = "SELECT * FROM $table WHERE $condition";
  88. $sql_result = Database::query($sql_query);
  89. $result = Database::fetch_array($sql_result);
  90. */
  91. /**
  92. * This function returns the correct complete name of any table of the main
  93. * database of which you pass the short name as a parameter.
  94. * Define table names as constants in this library and use them
  95. * instead of directly using magic words in your tool code.
  96. *
  97. * @param string $short_table_name, the name of the table
  98. * @return string
  99. */
  100. public static function get_main_table($short_table_name)
  101. {
  102. return self::format_table_name(self::get_main_database(), $short_table_name);
  103. }
  104. /**
  105. * This method returns the correct complete name of any course table of
  106. * which you pass the short name as a parameter.
  107. * Define table names as constants in this library and use them
  108. * instead of directly using magic words in your tool code.
  109. *
  110. * @param string $short_table_name, the name of the table
  111. * @return string
  112. *
  113. */
  114. public static function get_course_table($short_table_name)
  115. {
  116. return self::format_table_name(self::get_main_database(), DB_COURSE_PREFIX.$short_table_name);
  117. }
  118. /**
  119. * Returns the number of affected rows in the last database operation.
  120. * @param \Doctrine\DBAL\Driver\Statement $result
  121. * @return int
  122. */
  123. public static function affected_rows(\Doctrine\DBAL\Driver\Statement $result = null)
  124. {
  125. return $result->rowCount();
  126. //return self::use_default_connection($connection) ? mysql_affected_rows() : mysql_affected_rows($connection);
  127. }
  128. /**
  129. * Gets the array from a SQL result (as returned by Database::query) - help achieving database independence
  130. * @param resource The result from a call to sql_query (e.g. Database::query)
  131. * @param string Optional: "ASSOC","NUM" or "BOTH", as the constant used in mysql_fetch_array.
  132. * @return array Array of results as returned by php
  133. * @author Yannick Warnier <yannick.warnier@beeznest.com>
  134. */
  135. public static function fetch_array(\Doctrine\DBAL\Driver\Statement $result, $option = 'BOTH')
  136. {
  137. if ($result === false) {
  138. return array();
  139. }
  140. return $result->fetch(self::customOptionToDoctrineOption($option));
  141. /*return $option == 'ASSOC' ? mysql_fetch_array($result, MYSQL_ASSOC) : ($option == 'NUM' ? mysql_fetch_array(
  142. $result,
  143. MYSQL_NUM
  144. ) : mysql_fetch_array($result));*/
  145. }
  146. /**
  147. * Gets an associative array from a SQL result (as returned by Database::query).
  148. * This method is equivalent to calling Database::fetch_array() with 'ASSOC' value for the optional second parameter.
  149. * @param resource $result The result from a call to sql_query (e.g. Database::query).
  150. * @return array Returns an associative array that corresponds to the fetched row and moves the internal data pointer ahead.
  151. */
  152. public static function fetch_assoc(\Doctrine\DBAL\Driver\Statement $result)
  153. {
  154. return $result->fetch(PDO::FETCH_ASSOC);
  155. //return mysql_fetch_assoc($result);
  156. }
  157. /**
  158. * Gets the next row of the result of the SQL query (as returned by Database::query) in an object form
  159. * @param \Doctrine\DBAL\Driver\Statement The result from a call to Database::query())
  160. * @param string Optional class name to instanciate
  161. * @param array Optional array of parameters
  162. * @return object Object of class StdClass or the required class, containing the query result row
  163. * @author Yannick Warnier <yannick.warnier@dokeos.com>
  164. */
  165. public static function fetch_object(\Doctrine\DBAL\Driver\Statement $result)
  166. {
  167. // Waiting for http://www.doctrine-project.org/jira/browse/DBAL-544 in order to know which constant use.
  168. //return $result->fetch(\Doctrine\ORM\Query::HYDRATE_OBJECT);
  169. return $result->fetch(PDO::FETCH_OBJ);
  170. /*return !empty($class) ? (is_array($params) ? mysql_fetch_object($result, $class, $params) : mysql_fetch_object(
  171. $result,
  172. $class
  173. )) : mysql_fetch_object($result);*/
  174. }
  175. /**
  176. * Gets the array from a SQL result (as returned by Database::query) - help achieving database independence
  177. * @param \Doctrine\DBAL\Driver\Statement The result from a call to Database::query())
  178. * @return array Array of results as returned by php
  179. */
  180. public static function fetch_row(\Doctrine\DBAL\Driver\Statement $result)
  181. {
  182. return $result->fetch(PDO::FETCH_NUM);
  183. //return mysql_fetch_row($result);
  184. }
  185. /**
  186. * Gets the ID of the last item inserted into the database
  187. * @return int The last ID as returned by the DB function
  188. */
  189. public static function insert_id()
  190. {
  191. return self::$connectionWrite->lastInsertId();
  192. }
  193. /**
  194. * Gets the number of rows from the last query result - help achieving database independence
  195. * @param \Doctrine\DBAL\Driver\Statement
  196. * @return integer The number of rows contained in this result
  197. **/
  198. public static function num_rows(\Doctrine\DBAL\Driver\Statement $result)
  199. {
  200. return $result->rowCount();
  201. }
  202. /**
  203. * Acts as the relative *_result() function of most DB drivers and fetches a
  204. * specific line and a field
  205. * @param \Doctrine\DBAL\Driver\Statement The database resource to get data from
  206. * @param integer The row number
  207. * @param string Optional field name or number
  208. * @return mixed One cell of the result, or FALSE on error
  209. */
  210. public static function result(\Doctrine\DBAL\Driver\Statement $resource, $row, $field = 0)
  211. {
  212. if ($resource->rowCount() > 0) {
  213. $result = $resource->fetchAll(PDO::FETCH_BOTH);
  214. return $result[$row][$field];
  215. }
  216. return null;
  217. }
  218. /**
  219. * Frees all the memory associated with the provided result identifier.
  220. * @return bool Returns TRUE on success or FALSE on failure.
  221. * Notes: Use this method if you are concerned about how much memory is being used for queries that return large result sets.
  222. * Anyway, all associated result memory is automatically freed at the end of the script's execution.
  223. */
  224. public static function free_result(\Doctrine\DBAL\Driver\Statement $result)
  225. {
  226. $result->closeCursor();
  227. //return mysql_free_result($result);
  228. }
  229. /**
  230. * Detects if a query is going to modify something in the database in order to use the write connection
  231. * @param string $query
  232. * @return bool
  233. */
  234. public static function isWriteQuery($query)
  235. {
  236. $isWriteQuery = preg_match("/UPDATE(.*) FROM/i", $query) ||
  237. preg_match("/INSERT INTO/i", $query) ||
  238. preg_match("/REPLACE INTO/i", $query) ||
  239. preg_match("/DELETE FROM/i", $query);
  240. return $isWriteQuery;
  241. }
  242. /**
  243. * Escapes a string to insert into the database as text
  244. * @param string The string to escape
  245. * @return string The escaped string
  246. */
  247. public static function escape_string($string)
  248. {
  249. /* The pdo::quote function adds a "'" character we need to remove that '
  250. because in Chamilo, developers builds a query like this:
  251. $sql = "SELECT * FROM $table WHERE id = 'Database::escape_string($id)'";
  252. otherwise we will have an error because the query will be:
  253. SELECT * FROM user WHERE id = ''1'' instead of
  254. SELECT * FROM user WHERE id = '1'
  255. */
  256. // $string = '_@_'.self::$db->quote($string).'_@_';
  257. $string = self::$db->quote($string);
  258. return trim($string, "'");
  259. return $string;
  260. }
  261. /**
  262. * Executes a query in the database
  263. * @author Julio Montoya
  264. * @param string $query The SQL query
  265. * @return \Doctrine\DBAL\Driver\Statement
  266. */
  267. public static function query($query)
  268. {
  269. $isWriteQuery = self::isWriteQuery($query);
  270. if ($isWriteQuery) {
  271. $connection = self::$connectionWrite;
  272. } else {
  273. $connection = self::$connectionRead;
  274. }
  275. /* The solution below does not work because there are some case where we use the "LIKE" option like this:
  276. $sql = 'SELECT * FROM user WHERE id LIKE "%'.Database::escape_string($id).' %" ;
  277. Chamilo queries are formed in many ways:
  278. $sql = "SELECT * FROM user WHERE id = '".Database::escape_string($id)."'; or
  279. $sql = 'SELECT * FROM user WHERE id = '.Database::escape_string($id).';
  280. The problem here is that the function escape_string() calls the quote function that adds a "'" string.
  281. Instead of this we're adding a identifier __@__ so we can identify those cases and replace with a simple '
  282. */
  283. //var_dump($query);
  284. /*$query = str_replace(
  285. array(
  286. "\"_@_'",
  287. "'_@_\"",
  288. "'_@_'",
  289. "_@_'",
  290. "'_@_",
  291. ),
  292. "'",
  293. $query
  294. );*/
  295. //var_dump($query);
  296. return $connection->executeQuery($query);
  297. /*
  298. //@todo remove this before the stable release
  299. //Check if the table contains a c_ (means a course id)
  300. if (api_get_setting('server_type') === 'test' && strpos($query, 'c_')) {
  301. //Check if the table contains inner joins
  302. if (
  303. strpos($query, 'assoc_handle') === false &&
  304. strpos($query, 'olpc_peru_filter') === false &&
  305. strpos($query, 'allow_public_certificates') === false &&
  306. strpos($query, 'DROP TABLE IF EXISTS') === false &&
  307. strpos($query, 'thematic_advance') === false &&
  308. strpos($query, 'thematic_plan') === false &&
  309. strpos($query, 'track_c_countries') === false &&
  310. strpos($query, 'track_c_os') === false &&
  311. strpos($query, 'track_c_providers') === false &&
  312. strpos($query, 'track_c_referers') === false &&
  313. strpos($query, 'track_c_browsers') === false &&
  314. strpos($query, 'settings_current') === false &&
  315. strpos($query, 'branch_sync') === false &&
  316. strpos($query, 'branch_sync_log') === false &&
  317. strpos($query, 'branch_sync_log') === false &&
  318. strpos($query, 'branch_transaction') === false &&
  319. strpos($query, 'branch_transaction_status') === false &&
  320. strpos($query, 'dokeos_classic_2D') === false &&
  321. strpos($query, 'cosmic_campus') === false &&
  322. strpos($query, 'static_') === false &&
  323. strpos($query, 'public_admin') === false &&
  324. strpos($query, 'chamilo_electric_blue') === false &&
  325. strpos($query, 'wcag_anysurfer_public_pages') === false &&
  326. strpos($query, 'specific_field') === false &&
  327. strpos($query, 'down_doc_path') === false &&
  328. strpos($query, 'INNER JOIN') === false &&
  329. strpos($query, 'inner join') === false &&
  330. strpos($query, 'left join') === false &&
  331. strpos($query, 'LEFT JOIN') === false &&
  332. strpos($query, 'insert') === false &&
  333. strpos($query, 'INSERT') === false &&
  334. strpos($query, 'ALTER') === false &&
  335. strpos($query, 'alter') === false &&
  336. strpos($query, 'c_id') === false &&
  337. strpos($query, 'c_quiz_question_rel_category') === false &&
  338. strpos($query, 'c_quiz_category') === false &&
  339. strpos($query, 'c_quiz_rel_question') === false &&
  340. strpos($query, 'c_quiz_answer') === false &&
  341. strpos($query, 'c_quiz_question') === false &&
  342. strpos($query, 'c_quiz_rel_question') === false &&
  343. strpos($query, 'create table') === false &&
  344. strpos($query, 'CREATE TABLE') === false &&
  345. strpos($query, 'AUTO_INCREMENT') === false
  346. ) {
  347. //@todo remove this
  348. echo '<pre>';
  349. $message = '<h4>Dev message: please add the c_id field in this query or report this error in support.chamilo.org </h4>';
  350. $message .= $query;
  351. echo $message;
  352. echo '</pre>';
  353. }
  354. }
  355. */
  356. }
  357. public static function customOptionToDoctrineOption($option)
  358. {
  359. switch($option) {
  360. case 'ASSOC':
  361. return PDO::FETCH_ASSOC;
  362. break;
  363. case 'NUM':
  364. return PDO::FETCH_NUM;
  365. break;
  366. case 'BOTH':
  367. default:
  368. return PDO::FETCH_BOTH;
  369. break;
  370. }
  371. }
  372. /**
  373. * Stores a query result into an array.
  374. * @param \Doctrine\DBAL\Driver\Statement $result - the return value of the query
  375. * @param option BOTH, ASSOC, or NUM
  376. * @return array - the value returned by the query
  377. */
  378. public static function store_result(\Doctrine\DBAL\Driver\Statement $result, $option = 'BOTH')
  379. {
  380. return $result->fetchAll(self::customOptionToDoctrineOption($option));
  381. /*
  382. var_dump($a );
  383. $array = array();
  384. if ($result !== false) { // For isolation from database engine's behaviour.
  385. while ($row = self::fetch_array($result, $option)) {
  386. $array[] = $row;
  387. }
  388. }
  389. return $array;*/
  390. }
  391. /*
  392. Private methods
  393. You should not access these from outside the class
  394. No effort is made to keep the names / results the same.
  395. */
  396. /**
  397. * Structures a database and table name to ready them
  398. * for querying. The database parameter is considered not glued,
  399. * just plain e.g. COURSE001
  400. * @todo not sure if we need this now
  401. */
  402. private static function format_table_name($database, $table)
  403. {
  404. /*$glue = '`.`';
  405. $table_name = '`'.$database.$glue.$table.'`';
  406. */
  407. return $table;
  408. //return $table_name;
  409. }
  410. /*
  411. New useful DB functions
  412. */
  413. /**
  414. * Executes an insert to in the database (dbal already escape strings)
  415. * @param string table name
  416. * @param array An array of field and values
  417. * @param bool show query
  418. * @return int the id of the latest executed query
  419. */
  420. public static function insert($table_name, $attributes, $show_query = false)
  421. {
  422. $result = self::$connectionWrite->insert($table_name, $attributes);
  423. if ($result) {
  424. return self::insert_id();
  425. }
  426. return false;
  427. }
  428. /**
  429. * Experimental useful database finder
  430. * @todo lot of stuff to do here
  431. * @todo known issues, it doesn't work when using LIKE conditions
  432. * @example array('where'=> array('course_code LIKE "?%"'))
  433. * @example array('where'=> array('type = ? AND category = ?' => array('setting', 'Plugins'))
  434. * @example array('where'=> array('name = "Julio" AND lastname = "montoya"))
  435. */
  436. public static function select($columns, $table_name, $conditions = array(), $type_result = 'all', $option = 'ASSOC')
  437. {
  438. //$qb = self::$db->createQueryBuilder();
  439. $conditions = self::parse_conditions($conditions);
  440. //@todo we could do a describe here to check the columns ...
  441. $clean_columns = '';
  442. if (is_array($columns)) {
  443. $clean_columns = implode(',', $columns);
  444. } else {
  445. if ($columns == '*') {
  446. $clean_columns = '*';
  447. } else {
  448. $clean_columns = (string)$columns;
  449. }
  450. }
  451. /*$qb->select($clean_columns);
  452. $qb->from($table_name, 'table');
  453. $qb->orderBy('table.' . $sort_order, 'ASC');*/
  454. $sql = "SELECT $clean_columns FROM $table_name $conditions";
  455. //var_dump($sql);
  456. $result = self::query($sql);
  457. $array = array();
  458. if ($type_result == 'all') {
  459. while ($row = self::fetch_array($result, $option)) {
  460. if (isset($row['id'])) {
  461. $array[$row['id']] = $row;
  462. } else {
  463. $array[] = $row;
  464. }
  465. }
  466. } else {
  467. $array = self::fetch_array($result, $option);
  468. }
  469. return $array;
  470. }
  471. /**
  472. * Parses WHERE/ORDER conditions i.e array('where'=>array('id = ?' =>'4'), 'order'=>'id DESC'))
  473. * @todo known issues, it doesn't work when using LIKE conditions example: array('where'=>array('course_code LIKE "?%"'))
  474. * @param array
  475. * @return string
  476. * @todo lot of stuff to do here
  477. */
  478. static function parse_conditions($conditions)
  479. {
  480. if (empty($conditions)) {
  481. return '';
  482. }
  483. $return_value = $where_return = '';
  484. foreach ($conditions as $type_condition => $condition_data) {
  485. if ($condition_data == false) {
  486. continue;
  487. }
  488. $type_condition = strtolower($type_condition);
  489. switch ($type_condition) {
  490. case 'where':
  491. foreach ($condition_data as $condition => $value_array) {
  492. if (is_array($value_array)) {
  493. $clean_values = array();
  494. foreach ($value_array as $item) {
  495. $item = Database::escape_string($item);
  496. $clean_values[] = $item;
  497. }
  498. } else {
  499. $value_array = Database::escape_string($value_array);
  500. $clean_values = $value_array;
  501. }
  502. if (!empty($condition) && $clean_values != '') {
  503. $condition = str_replace('%', "'@percentage@'", $condition); //replace "%"
  504. $condition = str_replace("'?'", "%s", $condition);
  505. $condition = str_replace("?", "%s", $condition);
  506. $condition = str_replace("@%s@", "@-@", $condition);
  507. $condition = str_replace("%s", "'%s'", $condition);
  508. $condition = str_replace("@-@", "@%s@", $condition);
  509. //Treat conditons as string
  510. $condition = vsprintf($condition, $clean_values);
  511. $condition = str_replace('@percentage@', '%', $condition); //replace "%"
  512. $where_return .= $condition;
  513. }
  514. }
  515. if (!empty($where_return)) {
  516. $return_value = " WHERE $where_return";
  517. }
  518. break;
  519. case 'order':
  520. $order_array = $condition_data;
  521. if (!empty($order_array)) {
  522. // 'order' => 'id desc, name desc'
  523. $order_array = $order_array;
  524. $new_order_array = explode(',', $order_array);
  525. $temp_value = array();
  526. foreach ($new_order_array as $element) {
  527. $element = explode(' ', $element);
  528. $element = array_filter($element);
  529. $element = array_values($element);
  530. if (!empty($element[1])) {
  531. $element[1] = strtolower($element[1]);
  532. $order = 'DESC';
  533. if (in_array($element[1], array('desc', 'asc'))) {
  534. $order = $element[1];
  535. }
  536. $temp_value[] = $element[0].' '.$order.' ';
  537. } else {
  538. //by default DESC
  539. $temp_value[] = $element[0].' DESC ';
  540. }
  541. }
  542. if (!empty($temp_value)) {
  543. $return_value .= ' ORDER BY '.implode(', ', $temp_value);
  544. }
  545. }
  546. break;
  547. case 'limit':
  548. $limit_array = explode(',', $condition_data);
  549. if (!empty($limit_array)) {
  550. if (count($limit_array) > 1) {
  551. $return_value .= ' LIMIT '.intval($limit_array[0]).' , '.intval($limit_array[1]);
  552. } else {
  553. $return_value .= ' LIMIT '.intval($limit_array[0]);
  554. }
  555. }
  556. break;
  557. }
  558. }
  559. return $return_value;
  560. }
  561. public static function parse_where_conditions($conditions)
  562. {
  563. return self::parse_conditions(array('where' => $conditions));
  564. }
  565. /**
  566. * Deletes an item depending of conditions
  567. * @param string $table_name
  568. * @param array $where_conditions
  569. * @param bool $show_query
  570. * @return int
  571. */
  572. public static function delete($table_name, $where_conditions, $show_query = false)
  573. {
  574. //return self::$connectionWrite->delete($table_name, $where_conditions);
  575. $where_return = self::parse_where_conditions($where_conditions);
  576. $sql = "DELETE FROM $table_name $where_return ";
  577. if ($show_query) {
  578. echo $sql;
  579. echo '<br />';
  580. }
  581. $result = self::query($sql);
  582. $affected_rows = self::affected_rows($result);
  583. //@todo should return affected_rows for
  584. return $affected_rows;
  585. }
  586. /**
  587. * Experimental useful database update
  588. * @param string table name use Database::get_main_table
  589. * @param array array with values to updates, keys are the fields in the database:
  590. * @example: $params['name'] = 'Julio'; $params['lastname'] = 'Montoya';
  591. * @param array where conditions i.e array('id = ?' =>'4')
  592. * @param bool show query
  593. * @todo lot of stuff to do here
  594. */
  595. public static function update($table_name, $attributes, $where_conditions = array(), $show_query = false)
  596. {
  597. if (!empty($table_name) && !empty($attributes)) {
  598. $update_sql = '';
  599. //Cleaning attributes
  600. $count = 1;
  601. foreach ($attributes as $key => $value) {
  602. if (!is_array($value)) {
  603. $value = self::escape_string($value);
  604. }
  605. $update_sql .= "$key = '$value' ";
  606. if ($count < count($attributes)) {
  607. $update_sql .= ', ';
  608. }
  609. $count++;
  610. }
  611. if (!empty($update_sql)) {
  612. //Parsing and cleaning the where conditions
  613. $where_return = self::parse_where_conditions($where_conditions);
  614. $sql = "UPDATE $table_name SET $update_sql $where_return ";
  615. if ($show_query) {
  616. var_dump($sql);
  617. }
  618. $result = self::query($sql);
  619. $affected_rows = self::affected_rows($result);
  620. return $affected_rows;
  621. }
  622. }
  623. return false;
  624. }
  625. /*
  626. Query methods
  627. These methods execute a query and return the result(s).
  628. */
  629. /**
  630. * Counts the number of rows in a table
  631. * @param string $table The table of which the rows should be counted
  632. * @return int The number of rows in the given table.
  633. */
  634. public static function count_rows($table)
  635. {
  636. $obj = self::fetch_object(self::query("SELECT COUNT(*) AS n FROM $table"));
  637. return $obj->n;
  638. }
  639. /**
  640. * Returns a list of tables within a database. The list may contain all of the
  641. * available table names or filtered table names by using a pattern.
  642. * @param string $database (optional) The name of the examined database.
  643. * @param string $pattern (optional) A pattern for filtering table names as if it was needed for the SQL's LIKE clause, for example 'access_%'.
  644. * @deprecated
  645. * @return array Returns in an array the retrieved list of table names.
  646. */
  647. public static function get_tables($database = '', $pattern = '')
  648. {
  649. $result = array();
  650. $query = "SHOW TABLES";
  651. if (!empty($database)) {
  652. $query .= " FROM `".self::escape_string($database)."`";
  653. }
  654. if (!empty($pattern)) {
  655. $query .= " LIKE '".self::escape_string($pattern)."'";
  656. }
  657. $query_result = Database::query($query);
  658. while ($row = Database::fetch_row($query_result)) {
  659. $result[] = $row[0];
  660. }
  661. return $result;
  662. }
  663. /**
  664. * Returns a list of databases created on the server. The list may contain all of the
  665. * available database names or filtered database names by using a pattern.
  666. * @return array Returns in an array the retrieved list of database names.
  667. */
  668. public static function get_databases()
  669. {
  670. $sm = self::$db->getSchemaManager();
  671. return $sm->listDatabases();
  672. }
  673. }